package cn.com.acca.ma.service.impl;

import cn.com.acca.ma.common.util.DateUtil;
import cn.com.acca.ma.common.util.PropertiesUtil;
import cn.com.acca.ma.enumeration.ExchangeBoardInfo;
import cn.com.acca.ma.enumeration.IndexInfo;
import cn.com.acca.ma.enumeration.PythonApiResult;
import cn.com.acca.ma.enumeration.UpDown;
import cn.com.acca.ma.model.StockIndex;
import cn.com.acca.ma.model.StockInfo;
import cn.com.acca.ma.model.StockMovingAverage;
import cn.com.acca.ma.model.StockTransactionData;
import cn.com.acca.ma.service.StockTransactionDataService;
import cn.com.acca.ma.thread.AbstractThread;
import cn.com.acca.ma.thread.write.CollectStockTransactionDataThread_126;
import cn.com.acca.ma.thread.write.CollectStockTransactionDataThread_163;
import cn.com.acca.ma.thread.write.CollectStockTransactionDataThread_sohu;
import cn.com.acca.ma.thread.write.SupplementStockTransactionDataThread;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.StandardChartTheme;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.labels.StandardCategoryItemLabelGenerator;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.category.LineAndShapeRenderer;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.chart.title.TextTitle;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.data.time.Day;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.ui.RectangleInsets;

import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.io.*;
import java.math.BigDecimal;
import java.net.URL;
import java.net.URLConnection;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;
import org.apache.http.client.config.RequestConfig;

public class StockTransactionDataServiceImpl extends BaseServiceImpl<StockTransactionDataServiceImpl, StockMovingAverage> implements
        StockTransactionDataService {
    private List<StockMovingAverage> stockList = new ArrayList<StockMovingAverage>();

    public StockTransactionDataServiceImpl() {
        super();
    }

    /*********************************************************************************************************************
     *
     * 							从网络上获取数据，并插入到数据库中
     *
     *********************************************************************************************************************/
    /**
     * 从网络上获取数据，并插入到数据库。分别调用方法：readStockTransactionDataList, writeStockTransactionData
     * 和readStockCode。
     */
    public void insertStockTransactionData_sohu() {
        logger.info("从网络上获取数据，并插入到数据库");

        List<StockInfo> stockInfoList = stockInfoDao.getAllStockInfo();

        if (null != stockInfoList) {

            // 从stock-record.properties文件中获取参数
            InputStream inputStream = null;
            Properties properties = new Properties();
            // 开始时间
            String beginDate = null;
            // 结束时间
            String endDate = null;
            try {
                inputStream = new BufferedInputStream(new FileInputStream(STOCK_RECORD_PROPERTIES));
                properties.load(inputStream);

                beginDate = properties.getProperty("stockRecord.begin.date");
                endDate = properties.getProperty("stockRecord.end.date");

                logger.info("采集股票数据的开始时间为【" + beginDate + "】，结束时间为【" + endDate + "】");
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            StockTransactionDataService stockTransactionDataService = new StockTransactionDataServiceImpl();
            // 线程之间的间隔时间
            int threadIntervalSleepMillis = Integer.valueOf(PropertiesUtil.getValue(THREAD_PROPERTIES, "thread.interval.sleep.millis"));
            String stockInfoCodePrefix = PropertiesUtil.getValue(STOCK_RECORD_PROPERTIES, "stockRecord.sohu.code.prefix");

            // 查找所有股票在某一日的前收盘
            List lastClosePriceList = stockTransactionDataDao.findLastClosePrice(DateUtil.stringToDate(beginDate));

            for (int i = 0; i < stockInfoList.size(); i++) {
                StockInfo stockInfo = stockInfoList.get(i);
                String code = stockInfo.getCode();

                // 找出这支股票的前收盘价
                BigDecimal lastClosePrice = null;
                if (null != lastClosePriceList && lastClosePriceList.size() > 0) {
                    for (int j = 0; j < lastClosePriceList.size(); j++) {
                        Object[] objectArray = (Object[]) lastClosePriceList.get(j);
                        if (((String) objectArray[0]).equals(code)) {
                            lastClosePrice = (BigDecimal) objectArray[1];
                        }
                    }
                }

                // 启动消费者线程
                Thread producerThread = new Thread(new CollectStockTransactionDataThread_sohu(stockTransactionDataService,
                        stockInfoCodePrefix, code, beginDate, endDate, lastClosePrice));
                producerThread.start();
                try {
                    Thread.sleep(threadIntervalSleepMillis);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            // 每个一段时间（threadIntervalSleepStockTransactionDataCollectFinish）就检查一遍股票交易数据是否采集、存储完成
            int threadIntervalSleepStockTransactionDataCollectFinish = Integer.valueOf(PropertiesUtil.getValue(THREAD_PROPERTIES, "thread.interval.sleep.stockTransactionData.collect.finish"));
            while (true) {
                if (AbstractThread.stockTransactionDataCollectFinishAmount == stockInfoList.size()) {
                    break;
                } else {
                    try {
                        Thread.sleep(threadIntervalSleepStockTransactionDataCollectFinish);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        } else {
            logger.warn("从stock_info表中没有找到任何记录");
        }
    }

    /**
     * 注意：如果Python程序有修改，则每次通过adam运行这个python之前需要先给python程序打包
     * 调用baostock的python程序，向stock_transaction_data表中插入数据
     */
    @Override
    public void insertStockTransactionData_baoStock() {
        logger.info("调用baostock的python程序，向stock_transaction_data表中插入数据");

        Process process = null;
        BufferedReader in = null;
        try {
            String[] parameterArray = new String[]{"python",
                    DIR + "/src/main/python/dist/adam-python-1.0.tar.gz_files/adam-python-1.0/src/task/collect_stock_task.py"};
            process = Runtime.getRuntime().exec(parameterArray);
            in = new BufferedReader(new InputStreamReader(process.getInputStream(), "gbk"));
            String actionStr;
            while ((actionStr = in.readLine()) != null) {
                logger.info(actionStr);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            process.destroy();
        }
    }

    /**
     * 调用myquant接口，向stock_transaction_data表中插入数据
     */
    @Override
    public void writeStockTransactionDataByDate_myQuant() {
        logger.info("调用myquant接口，向stock_transaction_data表中插入数据");

        String filePath = PropertiesUtil.getValue(STOCK_RECORD_PROPERTIES, "adam3.api.file.path");
        String beginDate = PropertiesUtil.getValue(STOCK_RECORD_PROPERTIES, "stockRecord.begin.date");
        String endDate = PropertiesUtil.getValue(STOCK_RECORD_PROPERTIES, "stockRecord.end.date");
        String writeStockTransactionDataByDate = PropertiesUtil.getValue(STOCK_RECORD_PROPERTIES, "stockRecord.writeStockTransactionDataByDate");
        beginDate = String.format("%tF", DateUtil.stringToDate(beginDate));
        endDate = String.format("%tF", DateUtil.stringToDate(endDate));

        Process process = null;
        BufferedReader in = null;
        String[] parameterArray = new String[]{"python", filePath, "api",  writeStockTransactionDataByDate, beginDate, endDate};
        try {
            process = Runtime.getRuntime().exec(parameterArray);
            in = new BufferedReader(new InputStreamReader(process.getInputStream(), "gbk"));
            StringBuffer stringBuffer = new StringBuffer();
            String actionStr;
            while ((actionStr = in.readLine()) != null) {
                stringBuffer.append(actionStr);
                logger.debug("接口返回值：" + stringBuffer);
            }
            if (!PythonApiResult.FINISH.getCode().equals(stringBuffer.toString())){
                logger.warn("调用接口writeStockTransactionDataByDate失败，返回值：" + stringBuffer);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 从网络上获取数据，并插入到数据库。分别调用方法：readStockTransactionDataList, writeStockTransactionData
     * 和readStockCode。
     */
    public void insertStockTransactionData_163() {
        logger.info("从网络上获取数据，并插入到数据库");

        List<StockInfo> stockInfoList = stockInfoDao.getAllStockInfo();

        if (null != stockInfoList) {

            // 从stock-record.properties文件中获取参数
            InputStream inputStream = null;
            Properties properties = new Properties();
            // 开始时间
            String beginDate = null;
            // 结束时间
            String endDate = null;
            try {
                inputStream = new BufferedInputStream(new FileInputStream(STOCK_RECORD_PROPERTIES));
                properties.load(inputStream);

                beginDate = properties.getProperty("stockRecord.begin.date");
                endDate = properties.getProperty("stockRecord.end.date");

                logger.info("采集股票数据的开始时间为【" + beginDate + "】，结束时间为【" + endDate + "】");
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            StockTransactionDataService stockTransactionDataService = new StockTransactionDataServiceImpl();
            // 线程之间的间隔时间
            int threadIntervalSleepMillis = Integer.valueOf(PropertiesUtil.getValue(THREAD_PROPERTIES, "thread.interval.sleep.millis"));
            for (int i = 0; i < stockInfoList.size(); i++) {
                StockInfo stockInfo = stockInfoList.get(i);
                String code = stockInfo.getCode();
                String stockInfoCodePrefix = code.substring(0, 3);

                // 启动消费者线程
                Thread producerThread = new Thread(new CollectStockTransactionDataThread_163(stockTransactionDataService,
                        stockInfoCodePrefix, code, beginDate, endDate));
                producerThread.start();
                try {
                    Thread.sleep(threadIntervalSleepMillis);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            // 每个一段时间（threadIntervalSleepStockTransactionDataCollectFinish）就检查一遍股票交易数据是否采集、存储完成
            int threadIntervalSleepStockTransactionDataCollectFinish = Integer.valueOf(PropertiesUtil.getValue(THREAD_PROPERTIES, "thread.interval.sleep.stockTransactionData.collect.finish"));
            while (true) {
                if (AbstractThread.stockTransactionDataCollectFinishAmount == stockInfoList.size()) {
                    break;
                } else {
                    try {
                        Thread.sleep(threadIntervalSleepStockTransactionDataCollectFinish);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        } else {
            logger.warn("从stock_info表中没有找到任何记录");
        }
    }

//	public void insertAllRecords() {
//		logger.info("从网络上获取数据，并插入到数据库");
//
//		// 上证股票列表
//		List<StockTransactionData> shStockTransactionDataList;
//		// 科创版股票列表
//		List<StockTransactionData> kcbStockTransactionDataList;
//		// 深证股票、中小板股票列表
//		List<StockTransactionData> szStockTransactionDataList;
//		// 创业版股票列表
//		List<StockTransactionData> cybStockTransactionDataList;
//
//		// 股票代码列表
//		// 从表STOCK_INFO中读取全部数据
//		List<StockInfo> stockInfoList = this.readStockInfo();
//
//		Properties properties = new Properties();
//		// 股票开始时间
//		String stockTimeBegin = null;
//		// 股票结束时间
//		String stockTimeEnd = null;
//
//		// 上证股票、科创版股票代码开头的英文字母
////		String stockShCodePrefix = null;
//		// 上证股票、科创版股票代码开头，作为url中的参数
////		String stockShCodeBegin = null;
//		// 上证股票代码数字开头
//		String stockShCodeNumberBegin = null;
//		// 上证股票代码数字结尾
//		String stockShCodeNumberEnd = null;
//
//		// 科创版股票代码数字开头
//		String stockKcbCodeNumberBegin = null;
//		// 科创版股票代码数字结尾
//		String stockKcbCodeNumberEnd = null;
//
//		// 深证股票、中小板股票、创业板股票代码开头的英文字母
////		String stockSzCodePrefix = null;
//		// 深证股票、中小板股票、创业板股票代码开头，作为url中的参数
////		String stockSzCodeBegin = null;
//		// 深证股票、中小板股票代码数字开头
//		String stockSzCodeNumberBegin = null;
//		// 深证股票、中小板股票代码数字结尾
//		String stockSzCodeNumberEnd = null;
//
//		// 创业板股票代码数字开头
//		String stockCybCodeNumberBegin = null;
//		// 创业板股票代码数字结尾
//		String stockCybCodeNumberEnd = null;
//
//		// 从stock-record.properties文件中获取参数
//		InputStream inputStream = null;
//		try {
//			inputStream = new BufferedInputStream(new FileInputStream(STOCK_RECORD_PROPERTIES));
//			properties.load(inputStream);
//
//			stockTimeBegin = properties.getProperty("stockRecord.time.begin");
//			stockTimeEnd = properties.getProperty("stockRecord.time.end");
////			stockShCodePrefix = properties.getProperty("stockRecord.sh.code.prefix");
////			stockShCodeBegin = properties.getProperty("stockRecord.sh.code.begin");
//			stockShCodeNumberBegin = properties.getProperty("stockRecord.sh.code.number.begin");
//			stockShCodeNumberEnd = properties.getProperty("stockRecord.sh.code.number.end");
//			stockKcbCodeNumberBegin = properties.getProperty("stockRecord.kcb.code.number.begin");
//			stockKcbCodeNumberEnd = properties.getProperty("stockRecord.kcb.code.number.end");
////			stockSzCodePrefix = properties.getProperty("stockRecord.sz.code.prefix");
////			stockSzCodeBegin = properties.getProperty("stockRecord.sz.code.begin");
//			stockSzCodeNumberBegin = properties.getProperty("stockRecord.sz.code.number.begin");
//			stockSzCodeNumberEnd = properties.getProperty("stockRecord.sz.code.number.end");
//			stockCybCodeNumberBegin = properties.getProperty("stockRecord.cyb.code.number.begin");
//			stockCybCodeNumberEnd = properties.getProperty("stockRecord.cyb.code.number.end");
//		} catch (FileNotFoundException e) {
//			e.printStackTrace();
//		} catch (IOException e) {
//			e.printStackTrace();
//		} finally {
//			try {
//				inputStream.close();
//			} catch (IOException e) {
//				e.printStackTrace();
//			}
//		}
//
//		// 上证股票
//		logger.info("开始采集上证股票的交易数据");
//		for (int i = Integer.parseInt(stockShCodeNumberBegin); i <= Integer.parseInt(stockShCodeNumberEnd); i++) {
//			String codeNum = String.valueOf(i);
//			codeNum = ExchangeBoardInfo.SH_PREFIX.getUrlParamPrefix() + codeNum;
//
//			String url = DATA_SOURCE_URL_PREFIX_163 + codeNum + "&start=" + stockTimeBegin + "&end=" + stockTimeEnd
//				+ "&fields=TCLOSE;HIGH;LOW;TOPEN;LCLOSE;CHG;PCHG;TURNOVER;VOTURNOVER;VATURNOVER;TCAP;MCAP";
//			// 从网络上获取股票数据
//			shStockTransactionDataList = this.readStockTransactionDataList(url, codeNum);
//			logger.debug(url);
//
//			if (null == shStockTransactionDataList || shStockTransactionDataList.isEmpty()) {
//				continue;
//			}
//			for (StockInfo stockInfo : stockInfoList) {
//				if (stockInfo.getCode().equals(shStockTransactionDataList.get(0).getCode())) {
//					this.writeStockTransactionDataList(shStockTransactionDataList);
//					logger.debug(codeNum);
//				}
//			}
//		}
//
//		// 科创版股票
//		logger.info("开始采集科创版股票的交易数据");
//		for (int i = Integer.parseInt(stockKcbCodeNumberBegin); i <= Integer.parseInt(stockKcbCodeNumberEnd); i++) {
//			String codeNum = String.valueOf(i);
//			codeNum = ExchangeBoardInfo.KCB_PREFIX.getUrlParamPrefix() + codeNum;
//
//			String url = DATA_SOURCE_URL_PREFIX_163 + codeNum + "&start=" + stockTimeBegin + "&end=" + stockTimeEnd
//				+ "&fields=TCLOSE;HIGH;LOW;TOPEN;LCLOSE;CHG;PCHG;TURNOVER;VOTURNOVER;VATURNOVER;TCAP;MCAP";
//			// 从网络上获取股票数据
//			kcbStockTransactionDataList = this.readStockTransactionDataList(url, codeNum);
//			logger.debug(url);
//
//			if (null == kcbStockTransactionDataList || kcbStockTransactionDataList.isEmpty()) {
//				continue;
//			}
//
//			for (StockInfo stockInfo : stockInfoList) {
//				if (stockInfo.getCode().equals(kcbStockTransactionDataList.get(0).getCode())) {
//					this.writeStockTransactionDataList(kcbStockTransactionDataList);
//					logger.debug(codeNum);
//				}
//			}
//		}
//
//		// 深证股票、中小板股票
//		logger.info("开始采集深证股票、中小板股票的交易数据");
//		for (int i = Integer.parseInt(stockSzCodeNumberBegin); i <= Integer.parseInt(stockSzCodeNumberEnd); i++) {
//			String codeNum = String.valueOf(i);
//			// 深证股票、中小板股票的代码是以0开头的
//			while (codeNum.toCharArray().length != 6) {
//				codeNum = "0" + codeNum;
//			}
//			codeNum = ExchangeBoardInfo.SZ_SXB_PREFIX.getUrlParamPrefix() + codeNum;
//
//			String url = DATA_SOURCE_URL_PREFIX_163 + codeNum + "&start=" + stockTimeBegin + "&end=" + stockTimeEnd
//				+ "&fields=TCLOSE;HIGH;LOW;TOPEN;LCLOSE;CHG;PCHG;TURNOVER;VOTURNOVER;VATURNOVER;TCAP;MCAP";
//			szStockTransactionDataList = this.readStockTransactionDataList(url, codeNum);
//			logger.debug(url);
//			if (null == szStockTransactionDataList || szStockTransactionDataList.isEmpty()) {
//				continue;
//			}
//			for (StockInfo stockInfo : stockInfoList) {
//				if (stockInfo.getCode().equals(szStockTransactionDataList.get(0).getCode())) {
//					this.writeStockTransactionDataList(szStockTransactionDataList);
//					logger.debug(codeNum);
//				}
//			}
//		}
//
//		// 创业板股票
//		logger.info("开始采集创业板股票的交易数据");
//		for (int i = Integer.parseInt(stockCybCodeNumberBegin); i <= Integer.parseInt(stockCybCodeNumberEnd); i++) {
//			String codeNum = String.valueOf(i);
//			codeNum = ExchangeBoardInfo.CYB_PREFIX.getUrlParamPrefix() + codeNum;
//
//			String url = DATA_SOURCE_URL_PREFIX_163 + codeNum + "&start=" + stockTimeBegin + "&end=" + stockTimeEnd
//				+ "&fields=TCLOSE;HIGH;LOW;TOPEN;LCLOSE;CHG;PCHG;TURNOVER;VOTURNOVER;VATURNOVER;TCAP;MCAP";
//			cybStockTransactionDataList = this.readStockTransactionDataList(url, codeNum);
//			logger.debug(url);
//			if (null == cybStockTransactionDataList || cybStockTransactionDataList.isEmpty()) {
//				continue;
//			}
//			for (StockInfo stockInfo : stockInfoList) {
//				if (stockInfo.getCode().equals(cybStockTransactionDataList.get(0).getCode())) {
//					this.writeStockTransactionDataList(cybStockTransactionDataList);
//					logger.debug(codeNum);
//				}
//			}
//		}
//	}

    /**
     * 调用126的接口获取股票交易数据，并插入到数据库
     */
    public void insertStockTransactionData_126() {
        logger.info("调用126的接口获取股票交易数据，并插入到数据库");

        List<StockInfo> stockInfoList = stockInfoDao.getAllStockInfo();

        if (null != stockInfoList && stockInfoList.size() > 0) {
            // 从stock-record.properties文件中获取参数
            InputStream inputStream = null;
            Properties properties = new Properties();
            // 开始时间
            String beginDate = null;
            // 结束时间
            String endDate = null;
            try {
                inputStream = new BufferedInputStream(new FileInputStream(STOCK_RECORD_PROPERTIES));
                properties.load(inputStream);

                beginDate = properties.getProperty("stockTransactionData.beginDate");
                endDate = properties.getProperty("stockTransactionData.endDate");

                logger.info("采集股票数据的时间为从【" + beginDate + "】至【" + endDate + "】");
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            StockTransactionDataService stockTransactionDataService = new StockTransactionDataServiceImpl();
            // 线程之间的间隔时间
            int threadIntervalSleepMillis = Integer.valueOf(PropertiesUtil.getValue(THREAD_PROPERTIES, "thread.interval.sleep.millis"));
            // 查找所有股票在某一日的前收盘
            List lastClosePriceList = stockTransactionDataDao.findLastClosePrice(DateUtil.stringToDate(beginDate));

            for (int i = 0; i < stockInfoList.size(); i++) {
                StockInfo stockInfo = stockInfoList.get(i);
                String code = stockInfo.getCode();
                String stockInfoCodePrefix = code.substring(0, 3);

                // 找出这支股票的前收盘价
                BigDecimal lastClosePrice = null;
                if (null != lastClosePriceList && lastClosePriceList.size() > 0) {
                    for (int j = 0; j < lastClosePriceList.size(); j++) {
                        Object[] objectArray = (Object[]) lastClosePriceList.get(j);
                        if (((String) objectArray[0]).equals(code)) {
                            lastClosePrice = (BigDecimal) objectArray[1];
                        }
                    }
                }

                // 启动消费者线程
                Thread producerThread = new Thread(new CollectStockTransactionDataThread_126(stockTransactionDataService,
                        stockInfoCodePrefix, code, beginDate, endDate, lastClosePrice));
                producerThread.start();
                try {
                    Thread.sleep(threadIntervalSleepMillis);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            // 每个一段时间（threadIntervalSleepStockTransactionDataCollectFinish）就检查一遍股票交易数据是否采集、存储完成
            int threadIntervalSleepStockTransactionDataCollectFinish = Integer.valueOf(PropertiesUtil.getValue(THREAD_PROPERTIES, "thread.interval.sleep.stockTransactionData.collect.finish"));
            while (true) {
                if (AbstractThread.stockTransactionDataCollectFinishAmount == stockInfoList.size()) {
                    break;
                } else {
                    try {
                        Thread.sleep(threadIntervalSleepStockTransactionDataCollectFinish);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        } else {
            logger.warn("从stock_info表中没有找到任何记录");
        }
    }

    /**
     * 补充使用126接口没有的字段。使用126接口有些字段是空的，只能之后再使用163的接口将确实的字段补齐
     */
    public void supplementDataBy163Api() {
        logger.info("调用163的接口，补全由于之前使用126接口使得有些字段为空的记录");

        // 从stock-record.properties文件中获取参数
        InputStream inputStream = null;
        Properties properties = new Properties();
        // 开始时间
        String beginDate = null;
        // 结束时间
        String endDate = null;
        try {
            inputStream = new BufferedInputStream(new FileInputStream(STOCK_RECORD_PROPERTIES));
            properties.load(inputStream);

            beginDate = properties.getProperty("stockTransactionData.supplementData.beginDate");
            endDate = properties.getProperty("stockTransactionData.supplementData.endDate");

            logger.info("采集股票数据的时间为从【" + beginDate + "】至【" + endDate + "】");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        StockTransactionDataService stockTransactionDataService = new StockTransactionDataServiceImpl();
        // 线程之间的间隔时间
        int threadIntervalSleepMillis = Integer.valueOf(PropertiesUtil.getValue(THREAD_PROPERTIES, "thread.interval.sleep.millis"));
        // 查找turnover_rate、turnover、total_market_value、circulation_market_value字段为空的记录
        List<StockTransactionData> stockTransactionDataList = stockTransactionDataDao.findByTurnoverRateNullOrTurnoverNullOrTotalMarketValueNullOrCirculationMarketValueNull(
                beginDate, endDate);

        for (int i = 0; i < stockTransactionDataList.size(); i++) {
            StockTransactionData stockTransactionData = stockTransactionDataList.get(i);
            String code = stockTransactionData.getCode();
            String stockInfoCodePrefix = code.substring(0, 3);

            Integer id = stockTransactionData.getId();
            String date = DateUtil.dateToString(stockTransactionData.getDate());

            // 启动消费者线程。注意：开始时间和结束时间是一样的
            Thread producerThread = new Thread(new SupplementStockTransactionDataThread(stockTransactionDataService,
                    stockInfoCodePrefix, stockTransactionData, code, date, date));
            producerThread.start();
            try {
                Thread.sleep(threadIntervalSleepMillis);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        // 每个一段时间（threadIntervalSleepStockTransactionDataCollectFinish）就检查一遍股票交易数据是否采集、存储完成
        int threadIntervalSleepStockTransactionDataCollectFinish = Integer.valueOf(PropertiesUtil.getValue(THREAD_PROPERTIES,
                "thread.interval.sleep.stockTransactionData.collect.finish"));
        while (true) {
            if (AbstractThread.stockTransactionDataCollectFinishAmount == stockTransactionDataList.size()) {
                break;
            } else {
                try {
                    Thread.sleep(threadIntervalSleepStockTransactionDataCollectFinish);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    /**
     * 从网络中获取数据(sohu)
     *
     * @param url
     * @param codeNum
     * @return
     */
    @SuppressWarnings("deprecation")
    public List<StockTransactionData> readStockTransactionDataList_sohu(String url, String codeNum, BigDecimal lastClosePrice) {
        URL realUrl;
        URLConnection urlConnection;
        BufferedReader bufferedReader;
        File file;
        FileWriter fileWriter = null;
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        List<StockTransactionData> stockTransactionDataList = new ArrayList<>();

        try {
            httpClient = HttpClients.createDefault();
            HttpGet httpGet = new HttpGet(url);
            httpGet.setHeader("Accept", "application/json");
            httpGet.setHeader("Content-Type", "application/json");
            
            RequestConfig requestConfig = RequestConfig.custom()
                    .setConnectionRequestTimeout(60000000)
                    .setSocketTimeout(60000000)
                    .setConnectTimeout(60000000)
                    .build();
            httpGet.setConfig(requestConfig);
            response = httpClient.execute(httpGet);
            if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
                return null;
            }
            HttpEntity entity = response.getEntity();
            String res = EntityUtils.toString(entity);
            String result = new String(res.getBytes(), "GBK");
            JSONArray baseJSONArray = null;
            try {
                baseJSONArray = JSON.parseArray(result);
            } catch (JSONException e) {
//                e.printStackTrace();
                logger.warn("调用接口【" + url + "】，返回的数据为【" + result + "】，说明股票停牌，没有数据");
                return null;
            }

            JSONObject baseJsonObject = (JSONObject) baseJSONArray.get(0);
            JSONArray jsonArray = baseJsonObject.getJSONArray("hq");
            if (null != jsonArray && jsonArray.size() != 0) {
                for (int i = 0; i < jsonArray.size(); i++) {
                    StockTransactionData stockTransactionData = new StockTransactionData();
                    JSONArray dataJsonArray = (JSONArray) jsonArray.get(i);

                    Date date = DateUtil.stringToDate(dataJsonArray.getString(0));
                    stockTransactionData.setDate(date);
                    String code = baseJsonObject.getString("code").substring(3);
                    stockTransactionData.setCode(code);
                    stockTransactionData.setOpenPrice(new BigDecimal(dataJsonArray.getString(1)));
                    stockTransactionData.setClosePrice(new BigDecimal(dataJsonArray.getString(2)));
                    stockTransactionData.setChangeAmount(new BigDecimal(dataJsonArray.getString(3)));
                    String changeRange = dataJsonArray.getString(4);
                    stockTransactionData.setChangeRange(new BigDecimal(changeRange.substring(0, changeRange.length() - 1)));
                    stockTransactionData.setLowestPrice(new BigDecimal(dataJsonArray.getString(5)));
                    stockTransactionData.setHighestPrice(new BigDecimal(dataJsonArray.getString(6)));
                    stockTransactionData.setVolume(new BigDecimal(dataJsonArray.getString(7)));
                    stockTransactionData.setTurnover(new BigDecimal(dataJsonArray.getString(8)));
                    String turnoverRate = dataJsonArray.getString(9);
                    stockTransactionData.setTurnoverRate(new BigDecimal(turnoverRate.substring(0, turnoverRate.length() - 1)));
                    stockTransactionData.setLastClosePrice(lastClosePrice);
                    // 判断涨跌
                    // 平
                    if (null != stockTransactionData.getChangeRange() && stockTransactionData.getChangeRange().compareTo(BigDecimal.ZERO) == 0) {
                        stockTransactionData.setUpDown(BigDecimal.valueOf(UpDown.MIDDLE.getIndex()));
                    }
                    // 涨
                    if (null != stockTransactionData.getChangeRange() && stockTransactionData.getChangeRange().compareTo(BigDecimal.ZERO) == 1) {
                        stockTransactionData.setUpDown(BigDecimal.valueOf(UpDown.UP.getIndex()));
                    }
                    // 跌
                    if (null != stockTransactionData.getChangeRange() && stockTransactionData.getChangeRange().compareTo(BigDecimal.ZERO) == -1) {
                        stockTransactionData.setUpDown(BigDecimal.valueOf(UpDown.DOWN.getIndex()));
                    }
                    stockTransactionDataList.add(stockTransactionData);
                }
            }else{
                logger.warn("url：【" + url + "】返回值中的hq为空，可能根本就没有这只股票，或者这是新股票还没有上市");
            }
        } catch (IOException e) {
            e.printStackTrace();
            logger.warn("url：【" + url + "】连接异常，将连接信息记录在文件【"
                    + CONNECTION_EXCEPTION_FILE + "】中，用于之后手工添加数据");

            try {
                // 如果没有文件CONNECTION_EXCEPTION_FILE，则创建
                file = new File(CONNECTION_EXCEPTION_FILE);
                if (!file.exists()) {
                    file.createNewFile();
                }

                // 写入数据
                fileWriter = new FileWriter(CONNECTION_EXCEPTION_FILE, true);
                fileWriter.write(new Date() + "       " + e.getClass().getName() + "	" + url + "\n");

                // 递归调用
                List<StockTransactionData> timeOutList = this.readStockTransactionDataList_sohu(url, codeNum, lastClosePrice);
                for (int i = 0; i < timeOutList.size(); i++) {
                    stockTransactionDataList.add(timeOutList.get(i));
                }
            } catch (IOException e2) {
                e2.printStackTrace();
            } finally {
                try {
                    fileWriter.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        }
        return stockTransactionDataList;
    }

    /**
     * 从网络中获取数据(163)
     *
     * @param url
     * @param codeNum
     * @return
     */
    @SuppressWarnings("deprecation")
    public List<StockTransactionData> readStockTransactionDataList_163(String url, String codeNum) {
        URL realUrl;
        URLConnection urlConnection;
        BufferedReader bufferedReader;
        File file;
        FileWriter fileWriter = null;
        CSVParser csvparser = null;
        List<StockTransactionData> stockTransactionDataList = new ArrayList<>();

        try {
            realUrl = new URL(url);
            urlConnection = realUrl.openConnection();
            urlConnection.connect();
            bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), "GBK"));
            csvparser = CSVFormat.EXCEL.parse(bufferedReader);
            List<CSVRecord> csvRecordList = csvparser.getRecords();

            for (int i = 1; i < csvRecordList.size(); i++) {
                StockTransactionData stockTransactionData = new StockTransactionData();
                CSVRecord csvRecord = csvRecordList.get(i);
                int size = csvRecord.size();
                if (size >= 1 && null != csvRecordList.get(i) && !csvRecordList.get(i).equals("")
                        && null != csvRecordList.get(i).get(0) && !csvRecordList.get(i).get(0).equals("None")) {
                    String dateString = csvRecordList.get(i).get(0);
                    Date date = DateUtil.stringToDate(dateString);
                    stockTransactionData.setDate(date);
                }
                if (size >= 2 && null != csvRecordList.get(i) && !csvRecordList.get(i).equals("")
                        && null != csvRecordList.get(i).get(1) && !csvRecordList.get(i).get(1).equals("None")) {
                    stockTransactionData.setCode(csvRecordList.get(i).get(1).replace("'", ""));
                }
                // 注意：csvRecordList.get(i).get(2)为股票名称，这个暂时用不着
                // ......
                if (size >= 4 && null != csvRecordList.get(i) && !csvRecordList.get(i).equals("")
                        && null != csvRecordList.get(i).get(3) && !csvRecordList.get(i).get(3).equals("None")) {
                    stockTransactionData.setClosePrice(new BigDecimal(csvRecordList.get(i).get(3)));
                }
                if (size >= 5 && null != csvRecordList.get(i) && !csvRecordList.get(i).equals("")
                        && null != csvRecordList.get(i).get(4) && !csvRecordList.get(i).get(4).equals("None")) {
                    stockTransactionData.setHighestPrice(new BigDecimal(csvRecordList.get(i).get(4)));
                }
                if (size >= 6 && null != csvRecordList.get(i) && !csvRecordList.get(i).equals("")
                        && null != csvRecordList.get(i).get(5) && !csvRecordList.get(i).get(5).equals("None")) {
                    stockTransactionData.setLowestPrice(new BigDecimal(csvRecordList.get(i).get(5)));
                }
                if (size >= 7 && null != csvRecordList.get(i) && !csvRecordList.get(i).equals("")
                        && null != csvRecordList.get(i).get(6) && !csvRecordList.get(i).get(6).equals("None")) {
                    stockTransactionData.setOpenPrice(new BigDecimal(csvRecordList.get(i).get(6)));
                }
                if (size >= 8 && null != csvRecordList.get(i) && !csvRecordList.get(i).equals("")
                        && null != csvRecordList.get(i).get(7) && !csvRecordList.get(i).get(7).equals("None")) {
                    stockTransactionData.setLastClosePrice(new BigDecimal(csvRecordList.get(i).get(7)));
                }
                if (size >= 9 && null != csvRecordList.get(i) && !csvRecordList.get(i).equals("")
                        && null != csvRecordList.get(i).get(8) && !csvRecordList.get(i).get(8).equals("None")) {
                    stockTransactionData.setChangeAmount(new BigDecimal(csvRecordList.get(i).get(8)));
                }
                if (size >= 10 && null != csvRecordList.get(i) && !csvRecordList.get(i).equals("")
                        && null != csvRecordList.get(i).get(9) && !csvRecordList.get(i).get(9).equals("None")) {
                    stockTransactionData.setChangeRange(new BigDecimal(csvRecordList.get(i).get(9)));
                }
                if (size >= 11 && null != csvRecordList.get(i) && !csvRecordList.get(i).equals("")
                        && null != csvRecordList.get(i).get(10) && !csvRecordList.get(i).get(10).equals("None")) {
                    stockTransactionData.setTurnoverRate(new BigDecimal(csvRecordList.get(i).get(10)));
                }
                if (size >= 12 && null != csvRecordList.get(i) && !csvRecordList.get(i).equals("")
                        && null != csvRecordList.get(i).get(11) && !csvRecordList.get(i).get(11).equals("None")) {
                    stockTransactionData.setVolume(new BigDecimal(csvRecordList.get(i).get(11)));
                }
                if (size >= 13 && null != csvRecordList.get(i) && !csvRecordList.get(i).equals("")
                        && null != csvRecordList.get(i).get(12) && !csvRecordList.get(i).get(12).equals("None")) {
                    stockTransactionData.setTurnover(new BigDecimal(csvRecordList.get(i).get(12)));
                }
                if (size >= 14 && null != csvRecordList.get(i) && !csvRecordList.get(i).equals("")
                        && null != csvRecordList.get(i).get(13) && !csvRecordList.get(i).get(13).equals("None")) {
                    stockTransactionData.setTotalMarketValue(new BigDecimal(csvRecordList.get(i).get(13)));
                }
                if (size >= 15 && null != csvRecordList.get(i) && !csvRecordList.get(i).equals("")
                        && null != csvRecordList.get(i).get(14) && !csvRecordList.get(i).get(14).equals("None")) {
                    stockTransactionData.setCirculationMarketValue(new BigDecimal(csvRecordList.get(i).get(14)));
                }
                // 有的股票交易数据没有成交笔数，因此这个字段暂时先注释起来
                if (size >= 16 && null != csvRecordList.get(i) && !csvRecordList.get(i).equals("")
                        && null != csvRecordList.get(i).get(15) && !csvRecordList.get(i).get(15).equals("None")) {
                    stockTransactionData.setTransactionNumber(new BigDecimal(csvRecordList.get(i).get(15)));
                }
                // 判断是否为停牌。如果停牌则跳过
                if ((stockTransactionData.getOpenPrice() != null
                        && stockTransactionData.getOpenPrice().compareTo(BigDecimal.ZERO) == 0)
                        || (stockTransactionData.getClosePrice() != null
                        && stockTransactionData.getClosePrice().compareTo(BigDecimal.ZERO) == 0)
                        || (stockTransactionData.getHighestPrice() != null
                        && stockTransactionData.getHighestPrice().compareTo(BigDecimal.ZERO) == 0)
                        || (stockTransactionData.getLowestPrice() != null
                        && stockTransactionData.getLowestPrice().compareTo(BigDecimal.ZERO) == 0)
					/*&& (stockTransactionData.getTurnoverRate() != null
					&& stockTransactionData.getTurnoverRate().compareTo(BigDecimal.ZERO) == 0)
					&& (stockTransactionData.getVolume() != null
					&& stockTransactionData.getVolume().compareTo(BigDecimal.ZERO) == 0)
					&& (stockTransactionData.getTurnover() != null
					&& stockTransactionData.getTurnover().compareTo(BigDecimal.ZERO) == 0)
					&& stockTransactionData.getChangeAmount() == null
					&& stockTransactionData.getChangeRange() == null
					&& (stockTransactionData.getTotalMarketValue() != null
					&& stockTransactionData.getTotalMarketValue().compareTo(BigDecimal.ZERO) != 0)
					&& (stockTransactionData.getCirculationMarketValue() !=null
					&& stockTransactionData.getCirculationMarketValue().compareTo(BigDecimal.ZERO) != 0)*/) {
                    continue;
                }
                // 判断涨跌
                // 平
                if (null != stockTransactionData.getChangeRange() && stockTransactionData.getChangeRange().compareTo(BigDecimal.ZERO) == 0) {
                    stockTransactionData.setUpDown(BigDecimal.valueOf(UpDown.MIDDLE.getIndex()));
                }
                // 涨
                if (null != stockTransactionData.getChangeRange() && stockTransactionData.getChangeRange().compareTo(BigDecimal.ZERO) == 1) {
                    stockTransactionData.setUpDown(BigDecimal.valueOf(UpDown.UP.getIndex()));
                }
                // 跌
                if (null != stockTransactionData.getChangeRange() && stockTransactionData.getChangeRange().compareTo(BigDecimal.ZERO) == -1) {
                    stockTransactionData.setUpDown(BigDecimal.valueOf(UpDown.DOWN.getIndex()));
                }

                stockTransactionDataList.add(stockTransactionData);
            }
        } catch (IOException e) {
            e.printStackTrace();
            logger.warn("url：【" + url + "】连接异常，将连接信息记录在文件【"
                    + CONNECTION_EXCEPTION_FILE + "】中，用于之后手工添加数据");

            try {
                // 如果没有文件CONNECTION_EXCEPTION_FILE，则创建
                file = new File(CONNECTION_EXCEPTION_FILE);
                if (!file.exists()) {
                    file.createNewFile();
                }

                // 写入数据
                fileWriter = new FileWriter(CONNECTION_EXCEPTION_FILE, true);
                fileWriter.write(new Date() + "       " + e.getClass().getName() + "	" + url + "\n");

                // 递归调用
                List<StockTransactionData> timeOutList = this.readStockTransactionDataList_163(url, codeNum);
                for (int i = 0; i < timeOutList.size(); i++) {
                    stockTransactionDataList.add(timeOutList.get(i));
                }
            } catch (IOException e2) {
                e2.printStackTrace();
            } finally {
                try {
                    fileWriter.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        } finally {
            try {
                if (null != csvparser) {
                    csvparser.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return stockTransactionDataList;
    }


    /**
     * 从网络中获取数据(126)
     *
     * @param url
     * @param codeNum
     * @param beginDate
     * @param endDate
     * @param lastClosePrice
     * @return
     */
    @SuppressWarnings("deprecation")
    public List<StockTransactionData> readStockTransactionDataList_126(String url, String codeNum,
                                                                       String beginDate, String endDate, BigDecimal lastClosePrice) {

        File file;
        FileWriter fileWriter = null;
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;

        List<StockTransactionData> stockTransactionDataList = new ArrayList<>();

        try {
            httpClient = HttpClients.createDefault();
            HttpGet httpGet = new HttpGet(url);
            httpGet.setHeader("Accept", "application/json");
            httpGet.setHeader("Content-Type", "application/json");

            response = httpClient.execute(httpGet);
            if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
                return null;
            }
            HttpEntity entity = response.getEntity();
            String res = EntityUtils.toString(entity);
            String result = new String(res.getBytes(), "GBK");
            JSONObject jsonObject = JSONObject.parseObject(result);

            JSONArray jsonArray = jsonObject.getJSONArray("data");
            if (null != jsonArray) {
                for (int i = 0; i < jsonArray.size(); i++) {
                    JSONArray stockTransactionDataJSONArray = jsonArray.getJSONArray(i);
                    if (null != stockTransactionDataJSONArray) {
                        // 0：日期，1：开盘价，2：收盘价，3：最高价，4：最低价，5：成交量，6：涨跌幅
                        Date returnDate = DateUtil.stringToDate(stockTransactionDataJSONArray.getString(0));
                        // 只有交易日期在beginDate和endDate之间的数据才计算
                        boolean notInDateRange = false;
                        if (returnDate.before(DateUtil.stringToDate(beginDate))
                                || returnDate.after(DateUtil.stringToDate(endDate))) {
                            notInDateRange = true;
                        }
                        if (!notInDateRange) {
                            StockTransactionData stockTransactionData = new StockTransactionData();
                            stockTransactionData.setDate(returnDate);
                            String code = jsonObject.getString("symbol");
                            // code
                            stockTransactionData.setCode(code);
                            // 开盘价
                            stockTransactionData.setOpenPrice(stockTransactionDataJSONArray.getBigDecimal(1));
                            // 收盘价
                            stockTransactionData.setClosePrice(stockTransactionDataJSONArray.getBigDecimal(2));
                            // 最高价
                            stockTransactionData.setHighestPrice(stockTransactionDataJSONArray.getBigDecimal(3));
                            // 最低价
                            stockTransactionData.setLowestPrice(stockTransactionDataJSONArray.getBigDecimal(4));
                            // 成交量
                            stockTransactionData.setVolume(stockTransactionDataJSONArray.getBigDecimal(5));
                            // 涨跌幅
                            stockTransactionData.setChangeRange(stockTransactionDataJSONArray.getBigDecimal(6));
                            // 涨跌额
                            // 注意：有时某只股票在表stock_transaction_data中还没有交易记录，此时他的
                            // 前收盘是null，也就自然没有涨跌额了
                            if (null != lastClosePrice) {
                                stockTransactionData.setChangeAmount(stockTransactionData.getClosePrice().subtract(lastClosePrice));
                            }
                            // 前收盘
                            stockTransactionData.setLastClosePrice(lastClosePrice);
                            // 判断涨跌
                            // 平
                            if (null != stockTransactionData.getChangeRange() && stockTransactionData.getChangeRange().compareTo(BigDecimal.ZERO) == 0) {
                                stockTransactionData.setUpDown(BigDecimal.valueOf(UpDown.MIDDLE.getIndex()));
                            }
                            // 涨
                            if (null != stockTransactionData.getChangeRange() && stockTransactionData.getChangeRange().compareTo(BigDecimal.ZERO) == 1) {
                                stockTransactionData.setUpDown(BigDecimal.valueOf(UpDown.UP.getIndex()));
                            }
                            // 跌
                            if (null != stockTransactionData.getChangeRange() && stockTransactionData.getChangeRange().compareTo(BigDecimal.ZERO) == -1) {
                                stockTransactionData.setUpDown(BigDecimal.valueOf(UpDown.DOWN.getIndex()));
                            }
                            stockTransactionDataList.add(stockTransactionData);

                            // 注意：最后要将当日的收盘价设置为前收盘
                            lastClosePrice = stockTransactionData.getClosePrice();
                        }
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
            logger.warn("url：【" + url + "】连接异常，将连接信息记录在文件【"
                    + CONNECTION_EXCEPTION_FILE + "】中，用于之后手工添加数据");

            try {
                // 如果没有文件CONNECTION_EXCEPTION_FILE，则创建
                file = new File(CONNECTION_EXCEPTION_FILE);
                if (!file.exists()) {
                    file.createNewFile();
                }

                // 写入数据
                fileWriter = new FileWriter(CONNECTION_EXCEPTION_FILE, true);
                fileWriter.write(new Date() + "       " + e.getClass().getName() + "	" + url + "\n");

                // 递归调用
                List<StockTransactionData> timeOutList = this.readStockTransactionDataList_163(url, codeNum);
                for (int i = 0; i < timeOutList.size(); i++) {
                    stockTransactionDataList.add(timeOutList.get(i));
                }
            } catch (IOException e2) {
                e2.printStackTrace();
            } finally {
                try {
                    fileWriter.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        } finally {
            try {
                if (null != response) {
                    response.close();
                }
                if (null != httpClient) {
                    httpClient.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return stockTransactionDataList;
    }

    /**
     * 将从网络中读取的数据写入到表STOCK_MOVING_AVERAGE中。
     *
     * @param stockTransactionDataList
     */
    public void writeStockTransactionDataList(List<StockTransactionData> stockTransactionDataList) {
        stockTransactionDataDao.writeStockTransactionDataList(stockTransactionDataList);
    }

    /**
     * 将从网络中读取数据，更新STOCK_TRANSACTION_DATA表中的数据。
     *
     * @param stockTransactionData
     */
    public void updateStockTransactionData(StockTransactionData stockTransactionData) {
        stockTransactionDataDao.updateStockTransactionData(stockTransactionData);
    }

    /**
     * 从表STOCK_INFO中读取全部数据
     *
     * @return
     */
    public List<StockInfo> readStockInfo() {
        return stockTransactionDataDao.readStockInfo();
    }

    /*********************************************************************************************************************
     *
     * 							从网络上获取数据，存储在.json文件中；然后再解析文件，并插入到数据库中
     *
     *********************************************************************************************************************/
    /**
     * 从网络上获取数据，存储在.json文件中；然后再解析文件，并插入到数据库中
     */
    @SuppressWarnings("rawtypes")
    public void readAndWriteAllRecordsByJson() {
        // 上证股票列表
        List<StockTransactionData> stockTransactionDataList = new ArrayList<StockTransactionData>();
        // 深证股票列表
        List<StockMovingAverage> szStockList = new ArrayList<StockMovingAverage>();
        // 股票代码列表
        List<StockInfo> stockInfoList = this.readStockInfo();

        String stockTimeBegin = null;
        String stockTimeEnd = null;
        String stockShCodeBegin = null;
        String stockShCodeNumberBegin = null;
        String stockShCodeNumberEnd = null;
        String stockSzCodeBegin = null;
        String stockSzCodeNumberBegin = null;
        String stockSzCodeNumberEnd = null;
        String stockCybCodeNumberBegin = null;
        String stockCybCodeNumberEnd = null;

        try {
            SAXReader reader = new SAXReader();
            Document doc = reader.read(new File(STOCK_RECORD_XML));
            Element rootElt = doc.getRootElement();
            for (Iterator it = rootElt.elementIterator(); it.hasNext(); ) {
                Element element = (Element) it.next();
                if (element.attribute("id").getValue().equals("insertAllRecordsFromJson")) {
                    for (Iterator iterator = element.elementIterator(); iterator.hasNext(); ) {
                        Element elt = (Element) iterator.next();
                        if (elt.attributeValue("key").equals("stockRecord.time.begin")) {
                            stockTimeBegin = elt.attributeValue("value");
                        }
                        if (elt.attributeValue("key").equals("stockRecord.time.end")) {
                            stockTimeEnd = elt.attributeValue("value");
                        }
                        if (elt.attributeValue("key").equals("stockRecord.sh.code.begin")) {
                            stockShCodeBegin = elt.attributeValue("value");
                        }
                        if (elt.attributeValue("key").equals("stockRecord.sh.code.number.begin")) {
                            stockShCodeNumberBegin = elt.attributeValue("value");
                        }
                        if (elt.attributeValue("key").equals("stockRecord.sh.code.number.end")) {
                            stockShCodeNumberEnd = elt.attributeValue("value");
                        }
                        if (elt.attributeValue("key").equals("stockRecord.sz.code.begin")) {
                            stockSzCodeBegin = elt.attributeValue("value");
                        }
                        if (elt.attributeValue("key").equals("stockRecord.sz.code.number.begin")) {
                            stockSzCodeNumberBegin = elt.attributeValue("value");
                        }
                        if (elt.attributeValue("key").equals("stockRecord.sz.code.number.end")) {
                            stockSzCodeNumberEnd = elt.attributeValue("value");
                        }
                        if (elt.attributeValue("key").equals("stockRecord.cyb.code.number.begin")) {
                            stockCybCodeNumberBegin = elt.attributeValue("value");
                        }
                        if (elt.attributeValue("key").equals("stockRecord.cyb.code.number.end")) {
                            stockCybCodeNumberEnd = elt.attributeValue("value");
                        }
                    }
                }
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        }

        //清空ALL_RECORDS_IN_JSON.json文件的内容
        this.emptyJsonFile();

        //上证股票
        for (int i = Integer.parseInt(stockShCodeNumberBegin); i <= Integer.parseInt(stockShCodeNumberEnd); i++) {
            String codeNum = String.valueOf(i);
            while (codeNum.toCharArray().length != 6) {
                codeNum = "0" + codeNum;
            }

            String codeSh = stockShCodeBegin + codeNum;
            String url = DATA_SOURCE_URL_PREFIX_163 + codeSh + "&end_date=" + stockTimeEnd + "&begin_date=" + stockTimeBegin + "&type=plain";
            stockTransactionDataList.clear();
            stockTransactionDataList = this.readStockTransactionDataList_163(url, codeSh);
            logger.info(url);
            if (null == stockTransactionDataList || stockTransactionDataList.isEmpty()) {
                continue;
            }
            for (StockInfo stockInfo : stockInfoList) {
                if (stockInfo.getCode().toLowerCase().equals(stockTransactionDataList.get(0).getCode())) {
                    this.storeAllRecordsInJson(stockTransactionDataList);
                    logger.info(codeSh);
                }
            }
        }

        //深证股票,中小板股票
        for (int i = Integer.parseInt(stockSzCodeNumberBegin); i <= Integer.parseInt(stockSzCodeNumberEnd); i++) {
            String codeNum = String.valueOf(i);
            while (codeNum.toCharArray().length != 6) {
                codeNum = "0" + codeNum;
            }

            String codeSz = stockSzCodeBegin + codeNum;
            String url = DATA_SOURCE_URL_PREFIX_163 + codeSz + "&end_date=" + stockTimeEnd + "&begin_date=" + stockTimeBegin + "&type=plain";
            stockTransactionDataList.clear();
            stockTransactionDataList = this.readStockTransactionDataList_163(url, codeSz);
            logger.info(url);
            if (null == szStockList || szStockList.isEmpty()) {
                continue;
            }
            for (StockInfo stockInfo : stockInfoList) {
                if (stockInfo.getCode().toLowerCase().equals(szStockList.get(0).getStockCode())) {
                    this.storeAllRecordsInJson(stockTransactionDataList);
                    logger.info(codeSz);
                }
            }
        }

        //创业板股票
        for (int i = Integer.parseInt(stockCybCodeNumberBegin); i <= Integer.parseInt(stockCybCodeNumberEnd); i++) {
            String codeNum = String.valueOf(i);
            while (codeNum.toCharArray().length != 6) {
                codeNum = "0" + codeNum;
            }

            String codeSz = stockSzCodeBegin + codeNum;
            String url = DATA_SOURCE_URL_PREFIX_163 + codeSz + "&end_date=" + stockTimeEnd + "&begin_date=" + stockTimeBegin + "&type=plain";
            stockTransactionDataList.clear();
            stockTransactionDataList = this.readStockTransactionDataList_163(url, codeSz);
            logger.info(url);
            if (null == szStockList || szStockList.isEmpty()) {
                continue;
            }
            for (StockInfo stockInfo : stockInfoList) {
                if (stockInfo.getCode().toLowerCase().equals(szStockList.get(0).getStockCode())) {
                    this.storeAllRecordsInJson(stockTransactionDataList);
                    logger.info(codeSz);
                }
            }
        }
    }

    /**
     * 将从网络上获取的数据存储到.json文件中
     *
     * @param stockTransactionDataList
     */
    public void storeAllRecordsInJson(List<StockTransactionData> stockTransactionDataList) {
        ObjectMapper mapper = new ObjectMapper();
        String jsonString = null;
        File file = null;
        FileWriter fileWriter = null;
        file = new File(ALL_RECORDS_IN_JSON);

        try {
            fileWriter = new FileWriter(file, true);
        } catch (IOException e2) {
            e2.printStackTrace();
        }

        for (int i = 0; i < stockList.size(); i++) {
            try {
                jsonString = mapper.writeValueAsString(stockList.get(i));
            } catch (JsonGenerationException e) {
                e.printStackTrace();
            } catch (JsonMappingException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }

            try {
                fileWriter.append(jsonString + "\n");
                fileWriter.close();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        }
    }

    /**
     * 清空ALL_RECORDS_IN_JSON.json文件的内容
     */
    public void emptyJsonFile() {
        File f = new File(ALL_RECORDS_IN_JSON);
        FileWriter fw = null;
        try {
            fw = new FileWriter(f);
            fw.write("");
            fw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 将.json文件中的数据插入数据库
     */
    public void insertAllRecordsFromJson() {
        FileReader fr = null;
        BufferedReader br = null;
        String s;
        ObjectMapper mapper = new ObjectMapper();
        StockTransactionData stockTransactionData = new StockTransactionData();
        List<StockTransactionData> stockTransactionDataList = new ArrayList<StockTransactionData>();

        try {
            fr = new FileReader(ALL_RECORDS_IN_JSON);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        br = new BufferedReader(fr);

        try {
            while ((s = br.readLine()) != null) {
                stockTransactionData = mapper.readValue(s, StockTransactionData.class);
                stockTransactionDataList.add(stockTransactionData);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        try {
            fr.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        stockTransactionDataDao.insertAllRecordsFromJson(stockTransactionDataList);
    }

    /*********************************************************************************************************************
     *
     * 									                             更新每天的数据
     *
     *********************************************************************************************************************/
    /**
     * 更新表STOCK_MOVING_AVERAGE中某一日的FIVE，TEN，TWENTY，SIXTY和ONE_HUNDRED_TWENTY字段
     *
     * @param multithreading
     */
    public void writeMovingAverageByDate(boolean multithreading) {
        String date = PropertiesUtil.getValue(STOCK_RECORD_PROPERTIES, "stockRecord.movingAverage");
        stockTransactionDataDao.writeMovingAverageByDate(multithreading, date);
    }

    /**
     * 按照日期，计算所有股票的LAST_CLOSE_PRICE、CHANGE_AMOUNT、CHANGE_RANGE、CHANGE_RANGE_EX_RIGHT、UP_DOWN字段
     */
    public void writeLastClosePriceByDate() {
        String date = PropertiesUtil.getValue(STOCK_RECORD_PROPERTIES, "stockRecord.lastClosePrice.date");
        stockTransactionDataDao.writeLastClosePriceByDate(date);
    }

    /**
     * 调用myquant接口，根据日期，更新股票的总市值和流通市值
     */
    @Override
    public void writeMarketValueByDate_myQuant() {
        logger.info("调用myquant接口，根据日期，更新股票的总市值和流通市值");

        String filePath = PropertiesUtil.getValue(STOCK_RECORD_PROPERTIES, "adam3.api.file.path");
        String writeMarketValueByDate = PropertiesUtil.getValue(STOCK_RECORD_PROPERTIES, "stockRecord.marketValue.writeMarketValueByDate");
        String date = PropertiesUtil.getValue(STOCK_RECORD_PROPERTIES, "stockRecord.marketValue.date");
        date = String.format("%tF", DateUtil.stringToDate(date));

        Process process = null;
        BufferedReader in = null;
        String[] parameterArray = new String[]{"python", filePath, "api",  writeMarketValueByDate, date};
        try {
            process = Runtime.getRuntime().exec(parameterArray);
            in = new BufferedReader(new InputStreamReader(process.getInputStream(), "gbk"));
            StringBuffer stringBuffer = new StringBuffer();
            String actionStr;
            while ((actionStr = in.readLine()) != null) {
                stringBuffer.append(actionStr);
                logger.debug("接口返回值：" + stringBuffer);
            }
            if (!PythonApiResult.FINISH.getCode().equals(stringBuffer.toString())){
                logger.warn("调用接口writeMarketValueByDate失败，返回值：" + stringBuffer);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 调用myquant接口，根据日期，更新股票的pe、pb、ps、peg和dy
     */
    @Override
    public void writePePbPsPegDyByDate_myQuant() {
        logger.info("调用myquant接口，根据日期，更新股票的pe、pb、ps、peg和dy");

        String filePath = PropertiesUtil.getValue(STOCK_RECORD_PROPERTIES, "adam3.api.file.path");
        String writePeAndPbAndPsAndPegAndDyByDate = PropertiesUtil.getValue(STOCK_RECORD_PROPERTIES, "stockRecord.pePbPsPegDy.writePePbPsPegDyByDate");
        String date = PropertiesUtil.getValue(STOCK_RECORD_PROPERTIES, "stockRecord.pePbPsPegDy.date");
        date = String.format("%tF", DateUtil.stringToDate(date));

        Process process = null;
        BufferedReader in = null;
        String[] parameterArray = new String[]{"python", filePath, "api",  writePeAndPbAndPsAndPegAndDyByDate, date};
        try {
            process = Runtime.getRuntime().exec(parameterArray);
            in = new BufferedReader(new InputStreamReader(process.getInputStream(), "gbk"));
            StringBuffer stringBuffer = new StringBuffer();
            String actionStr;
            while ((actionStr = in.readLine()) != null) {
                stringBuffer.append(actionStr);
                logger.debug("接口返回值：" + actionStr);
            }
            if (!PythonApiResult.FINISH.getCode().equals(stringBuffer.toString())){
                logger.warn("调用接口writePeAndPbAndPsAndPegAndDyByDate，返回值：" + stringBuffer);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 更新表STOCK_TRANSACTION_DATA中某一日的UP_DOWN字段
     * stock_transaction_data表的up_down字段已经在获取数据时就计算好了，所以现在这个方法用不着了。
     */
    public void writeUpDownByDate() {
        String allStockOneDayUpDown = PropertiesUtil.getValue(STOCK_RECORD_PROPERTIES, "stockRecord.updown");
        stockTransactionDataDao.writeUpDownByDate(allStockOneDayUpDown);
    }

    /**
     * 更新表STOCK_TRANSACTION_DATA中某一日的EMA15，EMA26，DIF和DEA字段
     *
     * @param multithreading
     */
    public void writeMACDByDate(boolean multithreading) {
        String allStockOneDayAllMACD = PropertiesUtil.getValue(STOCK_RECORD_PROPERTIES, "stockRecord.MACD");
        stockTransactionDataDao.writeMACDByDate(multithreading, allStockOneDayAllMACD);
    }

    /**
     * 更新表STOCK_TRANSACTION_DATA中某一日的TODAY_UP_DOWN_PERCENTAGE字段
     */
    public void calUpDownPercentageByDate() {
        String todayUpDownPercentageDate = PropertiesUtil.getValue(STOCK_RECORD_PROPERTIES, "stockRecord.today.upDown.percentage");
        stockTransactionDataDao.calUpDownPercentageByDate(todayUpDownPercentageDate);
    }

    /**
     * 更新表STOCK_TRANSACTION_DATA中某一日的FIVE_DAY_VOLATILITY，TEN_DAY_VOLATILITY和TWENTY_DAY_VOLATILITY字段
     */
    public void calVolatilityByDate() {
        String volatilityDate = PropertiesUtil.getValue(STOCK_RECORD_PROPERTIES, "stockRecord.volatility");
        stockTransactionDataDao.calVolatilityByDate(volatilityDate);
    }

    /**
     * 更新stock_transaction_data表中某一日的KD指标
     *
     * @param multithreading
     */
    public void writeKDByDate(boolean multithreading) {
        String kdDate = PropertiesUtil.getValue(STOCK_RECORD_PROPERTIES, "stockRecord.KD");
        stockTransactionDataDao.writeKDByDate(multithreading, kdDate);
    }

    /**
     * 更新stock_transaction_data表中某一日的HA_OPEN_PRICE、HA_CLOSE_PRICE、HA_HIGHEST_PRICE、HA_LOWEST_PRICE
     *
     * @param multithreading
     */
    public void writeHaByDate(boolean multithreading) {
        String haDate = PropertiesUtil.getValue(STOCK_RECORD_PROPERTIES, "stockRecord.ha");
        stockTransactionDataDao.writeHaByDate(multithreading, haDate);
    }

    /**
     * 更新stock_transaction_data表中某一日的boll相关字段
     *
     * @param multithreading
     */
    public void writeBollByDate(boolean multithreading) {
        String bollDate = PropertiesUtil.getValue(STOCK_RECORD_PROPERTIES, "stockRecord.boll");
        stockTransactionDataDao.writeBollByDate(multithreading, bollDate);
    }

    /**
     * 更新stock_transaction_data表中某一日的bias相关字段
     *
     * @param multithreading
     */
    public void writeBiasByDate(boolean multithreading) {
        String biasDate = PropertiesUtil.getValue(STOCK_RECORD_PROPERTIES, "stockRecord.bias");
        stockTransactionDataDao.writeBiasByDate(multithreading, biasDate);
    }

    /**
     * 更新stock_transaction_data表中某一日的方差相关字段
     *
     * @param multithreading
     */
    public void writeVarianceByDate(boolean multithreading) {
        String varianceDate = PropertiesUtil.getValue(STOCK_RECORD_PROPERTIES, "stockRecord.variance");
        stockTransactionDataDao.writeVarianceByDate(multithreading, varianceDate);
    }

    /**
     * 更新stock_transaction_data_all表中某一日的成交量移动平均线相关字段
     *
     * @param multithreading
     */
    public void writeVolumeMaByDate(boolean multithreading) {
        String volumeMaDate = PropertiesUtil.getValue(STOCK_RECORD_PROPERTIES, "stockRecord.volumeMa");
        stockTransactionDataDao.writeVolumeMaByDate(multithreading, volumeMaDate);
    }

    /**
     * 更新stock_transaction_data_all表中某一日的成交额移动平均线相关字段
     *
     * @param multithreading
     */
    public void writeTurnoverMaByDate(boolean multithreading) {
        String turnoverMaDate = PropertiesUtil.getValue(STOCK_RECORD_PROPERTIES, "stockRecord.turnoverMa");
        stockTransactionDataDao.writeTurnoverMaByDate(multithreading, turnoverMaDate);
    }

    /*********************************************************************************************************************
     *
     * 									                             根据每日数据更新图表
     *
     *********************************************************************************************************************/
    /**
     * 创建移动平均线多头排列和空头排列图
     *
     * @param multithreading
     */
    @SuppressWarnings({})
    public void createMovingAverageBullRankShortOrderPicture(boolean multithreading) {

        // 创建最近10年的图
        logger.info("创建移动平均线多头排列和空头排列图--最近10年的图");
        String movingAverageTenYearBullRangeShortOrderBeginDate = PropertiesUtil.getValue(STOCK_RECORD_PICTURE_PROPERTIES, "stockRecordPicture.movingAverage.tenYear.bullRange.shortOrder.beginDate");
        String movingAverageTenYearBullRangeShortOrderEndDate = PropertiesUtil.getValue(STOCK_RECORD_PICTURE_PROPERTIES, "stockRecordPicture.movingAverage.tenYear.bullRange.shortOrder.endDate");
        this.paintMovingAverageBullRankShortOrderPicture(multithreading, movingAverageTenYearBullRangeShortOrderBeginDate, movingAverageTenYearBullRangeShortOrderEndDate, true);

        // 创建最近半年的图
        logger.info("创建移动平均线多头排列和空头排列图--最近半年的图");
        String movingAverageHalfYearBullRangeShortOrderBeginDate = PropertiesUtil.getValue(STOCK_RECORD_PICTURE_PROPERTIES, "stockRecordPicture.movingAverage.halfYear.bullRange.shortOrder.beginDate");
        String movingAverageHalfYearBullRangeShortOrderEndDate = PropertiesUtil.getValue(STOCK_RECORD_PICTURE_PROPERTIES, "stockRecordPicture.movingAverage.halfYear.bullRange.shortOrder.endDate");
        this.paintMovingAverageBullRankShortOrderPicture(multithreading, movingAverageHalfYearBullRangeShortOrderBeginDate, movingAverageHalfYearBullRangeShortOrderEndDate, false);
    }

    /**
     * 根据开始日期和结束日期，创建移动平均线多头排列和空头排列图。分别用来创建最近10年的图和半年的图
     *
     * @param multithreading
     * @param beginDate      开始时间
     * @param endDate        结束时间
     * @param flag           创建最近10年图时，flag为true，图片名称中有all；创建半年图时，flag为false，图片名称中没有all
     */
    @SuppressWarnings({"rawtypes", "deprecation"})
    public void paintMovingAverageBullRankShortOrderPicture(boolean multithreading, String beginDate, String endDate, boolean flag) {
        List<String> dateList = stockTransactionDataDao.getDateByCondition(multithreading, beginDate, endDate, flag);
        JFreeChart jfreechart;

        List bullRankNumberList = stockTransactionDataDao.getBullRankNumberWithinDate(beginDate, endDate, flag);
        List shortOrderNumberList = stockTransactionDataDao.getShortOrderNumberWithinDate(beginDate, endDate, flag);

        TimeSeries bullRankSeries = new TimeSeries("多头排列股票数量", org.jfree.data.time.Day.class);
        TimeSeries shortOrderSeries = new TimeSeries("空头排列股票数量", org.jfree.data.time.Day.class);
        TimeSeriesCollection timeSeriesCollection = new TimeSeriesCollection();

        /*
         * dateList集合中包含的是从开始日期至结束日期的所有交易日，bullRankNumberList集合和shortOrderNumberList集合中包含的是这段时间中
         * 每个交易日的多头排列和空头排列的数量，但是如果是0，则没有记录。因此dateList，bullRankNumberList和shortOrderNumberList这三个
         * 集合的大小可能是不一样的。下面两个for循环先判断dateList和bullRankNumberList或hortOrderNumberList的日期是否一样，如果不一样，
         * 则在dateList对应的日期上添加0，从而解决了这个问题。
         */
        for (int i = 0, j = 0; i < dateList.size() && j < bullRankNumberList.size(); ) {
            String[] str = dateList.get(i).toString().split("-");
            int year = Integer.parseInt(str[0]);
            int month = Integer.parseInt(str[1]);
            int day = Integer.parseInt(str[2]);
            Object[] obj = (Object[]) bullRankNumberList.get(j);
            if (dateList.get(i).toString().equals(obj[0].toString())) {
                bullRankSeries.add(new Day(day, month, year), Double.parseDouble(new Integer(obj[1].toString()).toString()));
                i++;
                j++;
            } else {
                bullRankSeries.add(new Day(day, month, year), 0);
                i++;
            }
        }
        for (int i = 0, j = 0; i < dateList.size() && j < shortOrderNumberList.size(); ) {
            String[] str = dateList.get(i).toString().split("-");
            int year = Integer.parseInt(str[0]);
            int month = Integer.parseInt(str[1]);
            int day = Integer.parseInt(str[2]);
            Object[] obj = (Object[]) shortOrderNumberList.get(j);
            if (dateList.get(i).toString().equals(obj[0].toString())) {
                shortOrderSeries.add(new Day(day, month, year), Double.parseDouble(new Integer(obj[1].toString()).toString()));
                i++;
                j++;
            } else {
                shortOrderSeries.add(new Day(day, month, year), 0);
                i++;
            }
        }

        timeSeriesCollection.addSeries(bullRankSeries);
        timeSeriesCollection.addSeries(shortOrderSeries);

        // 配置字体
        // X轴字体
        Font xFont = new Font("宋体", Font.PLAIN, 40);
        // Y轴字体
        Font yFont = new Font("宋体", Font.PLAIN, 40);
        // 底部字体
        Font bottomFont = new Font("宋体", Font.PLAIN, 40);
        // 图片标题字体
        Font titleFont = new Font("隶书", Font.BOLD, 50);

        jfreechart = ChartFactory.createTimeSeriesChart("多头排列股票数量（红色） & 空头排列股票数量（蓝色）",
                "日期", "数量", timeSeriesCollection, true, true, true);

        jfreechart.setBackgroundPaint(Color.white);
        // 图片标题
        jfreechart.setTitle(new TextTitle(jfreechart.getTitle().getText(), titleFont));
        // 底部字体
        jfreechart.getLegend().setItemFont(bottomFont);

        XYPlot xyPlot = (XYPlot) jfreechart.getPlot();
        xyPlot.setBackgroundPaint(Color.lightGray);
        xyPlot.setDomainGridlinePaint(Color.white);
        xyPlot.setRangeGridlinePaint(Color.white);
        xyPlot.setAxisOffset(new RectangleInsets(5D, 5D, 5D, 5D));
        xyPlot.setDomainCrosshairVisible(true);
        xyPlot.setRangeCrosshairVisible(true);

        // X轴
        ValueAxis domainAxis = xyPlot.getDomainAxis();
        // X轴标题字体
        domainAxis.setLabelFont(xFont);
        // Y轴
        ValueAxis rangeAxis = xyPlot.getRangeAxis();
        // Y轴标题字体
        rangeAxis.setLabelFont(yFont);

        org.jfree.chart.renderer.xy.XYItemRenderer xyItemRenderer = xyPlot.getRenderer();
        // 设置所有线条粗细
        xyItemRenderer.setStroke(new BasicStroke(5.0F));
        if (xyItemRenderer instanceof XYLineAndShapeRenderer) {
            XYLineAndShapeRenderer xylineandshaperenderer = (XYLineAndShapeRenderer) xyItemRenderer;
            xylineandshaperenderer.setBaseShapesVisible(true);
            xylineandshaperenderer.setBaseShapesFilled(true);
        }

        DateAxis dateaxis = (DateAxis) xyPlot.getDomainAxis();
        dateaxis.setDateFormatOverride(new SimpleDateFormat("yyyy-MM-dd"));

        try {
            FileOutputStream fos = new FileOutputStream(PICTURE_PATH + "bull_range_short_order/" + beginDate + "-" + endDate + (flag ? "_all" : "") + PICTURE_FORMAT);
            // 将统计图标输出成JPG文件
            ChartUtilities.writeChartAsJPEG(fos, // 输出到哪个输出流
                    1, // JPEG图片的质量，0~1之间
                    jfreechart, // 统计图标对象
                    imageWidth, // 宽
                    IMAGE_HEIGHT, // 高
                    null // ChartRenderingInfo 信息
            );
            fos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 创建MACD图
     *
     * @param multithreading
     */
    @SuppressWarnings({"deprecation", "rawtypes"})
    public void createMACDPicture(boolean multithreading) {
        logger.info("开始创建日线级别MACD指标的图表");

        String macdBeginDate = PropertiesUtil.getValue(STOCK_RECORD_PICTURE_PROPERTIES, "stockRecordPicture.macd.beginDate");
        String macdEndDate = PropertiesUtil.getValue(STOCK_RECORD_PICTURE_PROPERTIES, "stockRecordPicture.macd.endDate");

        // 获取数据
        List<String> dateList = stockTransactionDataDao.findDistinctDateBetweenDate(multithreading, macdBeginDate, macdEndDate);
        JFreeChart jfreechart;

        // 获取某一段时间内平均价格中的最大价格和最小价格
        List maxMinCloseList = stockTransactionDataDao.getMaxMinAverageCloseWeek(multithreading, macdBeginDate, macdEndDate);
        double maxClosePirce = Double.parseDouble(((Object[]) maxMinCloseList.get(0))[0].toString());
        double minClosePirce = Double.parseDouble(((Object[]) maxMinCloseList.get(0))[1].toString());
        // 获取某一段时间内dif和dea的最大值和最小值
        List maxMinDifDeaList = stockTransactionDataDao.getMaxMinDifDea(multithreading, macdBeginDate, macdEndDate);
        double maxDif = Double.parseDouble(((Object[]) maxMinDifDeaList.get(0))[0].toString());
        double minDif = Double.parseDouble(((Object[]) maxMinDifDeaList.get(0))[1].toString());
        double maxDea = Double.parseDouble(((Object[]) maxMinDifDeaList.get(0))[2].toString());
        double minDea = Double.parseDouble(((Object[]) maxMinDifDeaList.get(0))[3].toString());

        List averageAllCloseList = stockTransactionDataDao.getAverageCloseWithDate(multithreading, macdBeginDate, macdEndDate, false, "all");
        TimeSeries difSeries = new TimeSeries("DIF Index", org.jfree.data.time.Day.class);
        TimeSeries deaSeries = new TimeSeries("DEA Index", org.jfree.data.time.Day.class);
        TimeSeries averageCloseSeries = new TimeSeries("Average Stock Close", org.jfree.data.time.Day.class);
        TimeSeriesCollection timeSeriesCollection = new TimeSeriesCollection();

        for (int i = 0; i < dateList.size(); i++) {
            String[] str = dateList.get(i).toString().split("-");
            int year = Integer.parseInt(str[0]);
            int month = Integer.parseInt(str[1]);
            int day = Integer.parseInt(str[2]);
            double value = Double.valueOf(stockTransactionDataDao.getAverageDif(multithreading, dateList.get(i).replace("-", "")));
            difSeries.add(new Day(day, month, year), value);
        }
        for (int i = 0; i < dateList.size(); i++) {
            String[] str = dateList.get(i).toString().split("-");
            int year = Integer.parseInt(str[0]);
            int month = Integer.parseInt(str[1]);
            int day = Integer.parseInt(str[2]);
            double value = Double.valueOf(stockTransactionDataDao.getAverageDea(multithreading, dateList.get(i).replace("-", "")));
            deaSeries.add(new Day(day, month, year), value);
        }
        for (int i = 0; i < dateList.size(); i++) {
            String[] str = dateList.get(i).toString().split("-");
            int year = Integer.parseInt(str[0]);
            int month = Integer.parseInt(str[1]);
            int day = Integer.parseInt(str[2]);
            Object[] obj = (Object[]) averageAllCloseList.get(i);
            double value = this.adjustData(maxClosePirce, minClosePirce, maxDif, minDif, Double.parseDouble(obj[1].toString()));
            averageCloseSeries.add(new Day(day, month, year), value);
        }

        timeSeriesCollection.addSeries(difSeries);
        timeSeriesCollection.addSeries(deaSeries);
        timeSeriesCollection.addSeries(averageCloseSeries);

        jfreechart = ChartFactory.createTimeSeriesChart("DIF Index & DEA Index $ Average Stock Close",
                "Date", "Index", timeSeriesCollection, true, true, true);
        jfreechart.setBackgroundPaint(Color.white);
        XYPlot xyplot = (XYPlot) jfreechart.getPlot();
        xyplot.setBackgroundPaint(Color.lightGray);
        xyplot.setDomainGridlinePaint(Color.white);
        xyplot.setRangeGridlinePaint(Color.white);
        xyplot.setAxisOffset(new RectangleInsets(5D, 5D, 5D, 5D));
        xyplot.setDomainCrosshairVisible(true);
        xyplot.setRangeCrosshairVisible(true);
        org.jfree.chart.renderer.xy.XYItemRenderer xyitemrenderer = xyplot.getRenderer();
        if (xyitemrenderer instanceof XYLineAndShapeRenderer) {
            XYLineAndShapeRenderer xylineandshaperenderer = (XYLineAndShapeRenderer) xyitemrenderer;
            xylineandshaperenderer.setBaseShapesVisible(true);
            xylineandshaperenderer.setBaseShapesFilled(true);
            xylineandshaperenderer.setSeriesPaint(2, Color.BLACK);
        }
        DateAxis dateaxis = (DateAxis) xyplot.getDomainAxis();
        dateaxis.setDateFormatOverride(new SimpleDateFormat("yyyy-MM-dd"));

        try {
            FileOutputStream fos = new FileOutputStream(PICTURE_PATH + "macd/" + macdBeginDate + "-" + macdEndDate + PICTURE_FORMAT);
            // 将统计图标输出成JPG文件
            ChartUtilities.writeChartAsJPEG(fos, // 输出到哪个输出流
                    1, // JPEG图片的质量，0~1之间
                    jfreechart, // 统计图标对象
                    imageWidth, // 宽
                    IMAGE_HEIGHT, // 高
                    null // ChartRenderingInfo 信息
            );
            fos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 创建股票收盘价图
     *
     * @param multithreading
     * @param tenYear        是否创建最近十年的图表
     */
    public void createClosePicture(boolean multithreading, boolean tenYear) {
        // 创建最近10年的图
        if (tenYear) {
            logger.info("开始创建股票收盘价图（最近10年）");
            String closeTenYearBeginDate = PropertiesUtil.getValue(STOCK_RECORD_PICTURE_PROPERTIES, "stockRecordPicture.tenYear.close.beginDate");
            String closeTenYearEndDate = PropertiesUtil.getValue(STOCK_RECORD_PICTURE_PROPERTIES, "stockRecordPicture.tenYear.close.endDate");
            this.paintClosePicture(multithreading, closeTenYearBeginDate, closeTenYearEndDate, true);
        }

        // 创建最近半年的图
        logger.info("开始创建股票收盘价图（最近半年）");
        String closeHalfYearBeginDate = PropertiesUtil.getValue(STOCK_RECORD_PICTURE_PROPERTIES, "stockRecordPicture.halfYear.close.beginDate");
        String closeHalfYearEndDate = PropertiesUtil.getValue(STOCK_RECORD_PICTURE_PROPERTIES, "stockRecordPicture.halfYear.close.endDate");
        this.paintClosePicture(multithreading, closeHalfYearBeginDate, closeHalfYearEndDate, false);
    }

    /**
     * 创建KD图
     *
     * @param multithreading
     */
    public void createKDPicture(boolean multithreading) {
        logger.info("开始创建日线级别KD指标的图表");

        String kdBeginDate = PropertiesUtil.getValue(STOCK_RECORD_PICTURE_PROPERTIES, "stockRecordPicture.kd.beginDate");
        String kdEndDate = PropertiesUtil.getValue(STOCK_RECORD_PICTURE_PROPERTIES, "stockRecordPicture.kd.endDate");

        // 获取数据
        List<String> dateList = stockTransactionDataDao.findDistinctDateBetweenDate(multithreading, kdBeginDate, kdEndDate);
        JFreeChart jfreechart;

        // 获取某一段时间内平均价格中的最大价格和最小价格
        List maxMinCloseList = stockTransactionDataDao.getMaxMinAverageCloseWeek(multithreading, kdBeginDate, kdEndDate);
        double maxClose = Double.parseDouble(((Object[]) maxMinCloseList.get(0))[0].toString());
        double minClose = Double.parseDouble(((Object[]) maxMinCloseList.get(0))[1].toString());
        // 获取某一段时间内k和d的最大值和最小值
        List maxMinKDList = stockTransactionDataDao.getMaxMinKD(multithreading, kdBeginDate, kdEndDate);
        double maxK = Double.parseDouble(((Object[]) maxMinKDList.get(0))[0].toString());
        double minK = Double.parseDouble(((Object[]) maxMinKDList.get(0))[1].toString());
        double maxD = Double.parseDouble(((Object[]) maxMinKDList.get(0))[2].toString());
        double minD = Double.parseDouble(((Object[]) maxMinKDList.get(0))[3].toString());

        List averageAllCloseList = stockTransactionDataDao.getAverageCloseWithDate(multithreading, kdBeginDate, kdEndDate, false, "all");
        TimeSeries kSeries = new TimeSeries("K Index", org.jfree.data.time.Day.class);
        TimeSeries dSeries = new TimeSeries("D Index", org.jfree.data.time.Day.class);
        TimeSeries averageCloseSeries = new TimeSeries("Average Stock Close", org.jfree.data.time.Day.class);
        TimeSeriesCollection timeSeriesCollection = new TimeSeriesCollection();

        for (int i = 0; i < dateList.size(); i++) {
            String[] str = dateList.get(i).toString().split("-");
            int year = Integer.parseInt(str[0]);
            int month = Integer.parseInt(str[1]);
            int day = Integer.parseInt(str[2]);
            double value = Double.valueOf(stockTransactionDataDao.getAverageK(multithreading, dateList.get(i).replace("-", "")));
            kSeries.add(new Day(day, month, year), value);
        }
        for (int i = 0; i < dateList.size(); i++) {
            String[] str = dateList.get(i).toString().split("-");
            int year = Integer.parseInt(str[0]);
            int month = Integer.parseInt(str[1]);
            int day = Integer.parseInt(str[2]);
            double value = Double.valueOf(stockTransactionDataDao.getAverageD(multithreading, dateList.get(i).replace("-", "")));
            dSeries.add(new Day(day, month, year), value);
        }
        for (int i = 0; i < dateList.size(); i++) {
            String[] str = dateList.get(i).toString().split("-");
            int year = Integer.parseInt(str[0]);
            int month = Integer.parseInt(str[1]);
            int day = Integer.parseInt(str[2]);
            Object[] obj = (Object[]) averageAllCloseList.get(i);
            double value = this.adjustData(maxClose, minClose, maxK, minK, Double.parseDouble(obj[1].toString()));
            averageCloseSeries.add(new Day(day, month, year), value);
        }

        timeSeriesCollection.addSeries(kSeries);
        timeSeriesCollection.addSeries(dSeries);
        timeSeriesCollection.addSeries(averageCloseSeries);

        jfreechart = ChartFactory.createTimeSeriesChart("K Index & D Index $ Average Stock Close",
                "Date", "Index", timeSeriesCollection, true, true, true);
        jfreechart.setBackgroundPaint(Color.white);
        XYPlot xyplot = (XYPlot) jfreechart.getPlot();
        xyplot.setBackgroundPaint(Color.lightGray);
        xyplot.setDomainGridlinePaint(Color.white);
        xyplot.setRangeGridlinePaint(Color.white);
        xyplot.setAxisOffset(new RectangleInsets(5D, 5D, 5D, 5D));
        xyplot.setDomainCrosshairVisible(true);
        xyplot.setRangeCrosshairVisible(true);
        org.jfree.chart.renderer.xy.XYItemRenderer xyitemrenderer = xyplot.getRenderer();
        if (xyitemrenderer instanceof XYLineAndShapeRenderer) {
            XYLineAndShapeRenderer xylineandshaperenderer = (XYLineAndShapeRenderer) xyitemrenderer;
            xylineandshaperenderer.setBaseShapesVisible(true);
            xylineandshaperenderer.setBaseShapesFilled(true);
            xylineandshaperenderer.setSeriesPaint(2, Color.BLACK);
        }
        DateAxis dateaxis = (DateAxis) xyplot.getDomainAxis();
        dateaxis.setDateFormatOverride(new SimpleDateFormat("yyyy-MM-dd"));

        try {
            FileOutputStream fos = new FileOutputStream(PICTURE_PATH + "kd/" + kdBeginDate + "-" + kdEndDate + PICTURE_FORMAT);
            // 将统计图标输出成JPG文件
            ChartUtilities.writeChartAsJPEG(fos, // 输出到哪个输出流
                    1, // JPEG图片的质量，0~1之间
                    jfreechart, // 统计图标对象
                    imageWidth, // 宽
                    IMAGE_HEIGHT, // 高
                    null // ChartRenderingInfo 信息
            );
            fos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 创建close_price金叉MA5图
     *
     * @param multithreading
     */
    public void createClosePriceGoldCrossMa5Picture(boolean multithreading) {
        logger.info("开始创建close_price金叉MA5的图表");

        String closePriceGoldCrossMa5BeginDate = PropertiesUtil.getValue(STOCK_RECORD_PICTURE_PROPERTIES, "stockRecordPicture.closePrice.goldCross.ma5.beginDate");
        String closePriceGoldCrossMa5EndDate = PropertiesUtil.getValue(STOCK_RECORD_PICTURE_PROPERTIES, "stockRecordPicture.closePrice.goldCross.ma5.endDate");

        // 获取数据
        List<String> dateList = stockTransactionDataDao.findDistinctDateBetweenDate(multithreading, closePriceGoldCrossMa5BeginDate, closePriceGoldCrossMa5EndDate);
        JFreeChart jfreechart;

        // 获取某一段时间内平均价格中的最大价格和最小价格
//		List maxMinCloseList = stockTransactionDataDao.getMaxMinAverageCloseWeek(multithreading, closePriceGoldCrossMa5BeginDate, closePriceGoldCrossMa5EndDate);
//		double maxAverageClosePrice = Double.parseDouble(((Object[]) maxMinCloseList.get(0))[0].toString());
//		double minAverageClosePrice = Double.parseDouble(((Object[]) maxMinCloseList.get(0))[1].toString());
        // 获取某一段时间内close_price和ma5的最大值和最小值
//		List maxMinClosePriceAndMa5List = stockTransactionDataDao.getMaxMinClosePriceAndMa5(multithreading, closePriceGoldCrossMa5BeginDate, closePriceGoldCrossMa5EndDate);
//		double maxClosePrice = Double.parseDouble(((Object[]) maxMinClosePriceAndMa5List.get(0))[0].toString());
//		double minClosePrice = Double.parseDouble(((Object[]) maxMinClosePriceAndMa5List.get(0))[1].toString());
//		double maxMa5 = Double.parseDouble(((Object[]) maxMinClosePriceAndMa5List.get(0))[2].toString());
//		double minMa5 = Double.parseDouble(((Object[]) maxMinClosePriceAndMa5List.get(0))[3].toString());

//		List averageAllCloseList = stockTransactionDataDao.getAverageCloseWithDate(multithreading, closePriceGoldCrossMa5BeginDate, closePriceGoldCrossMa5EndDate, false, "all");
        TimeSeries closePriceSeries = new TimeSeries("close_price Index", org.jfree.data.time.Day.class);
        TimeSeries ma5Series = new TimeSeries("MA5 Index", org.jfree.data.time.Day.class);
//		TimeSeries averageCloseSeries = new TimeSeries("Average Stock Close", org.jfree.data.time.Day.class);
        TimeSeriesCollection timeSeriesCollection = new TimeSeriesCollection();

        for (int i = 0; i < dateList.size(); i++) {
            String[] str = dateList.get(i).toString().split("-");
            int year = Integer.parseInt(str[0]);
            int month = Integer.parseInt(str[1]);
            int day = Integer.parseInt(str[2]);
            double value = Double.valueOf(stockTransactionDataDao.getAverageClosePrice(multithreading, dateList.get(i).replace("-", "")));
            closePriceSeries.add(new Day(day, month, year), value);
        }
        for (int i = 0; i < dateList.size(); i++) {
            String[] str = dateList.get(i).toString().split("-");
            int year = Integer.parseInt(str[0]);
            int month = Integer.parseInt(str[1]);
            int day = Integer.parseInt(str[2]);
            double value = Double.valueOf(stockTransactionDataDao.getAverageMA5(multithreading, dateList.get(i).replace("-", "")));
            ma5Series.add(new Day(day, month, year), value);
        }
//		for (int i = 0; i < dateList.size(); i++) {
//			String[] str = dateList.get(i).toString().split("-");
//			int year = Integer.parseInt(str[0]);
//			int month = Integer.parseInt(str[1]);
//			int day = Integer.parseInt(str[2]);
//			Object[] obj = (Object[]) averageAllCloseList.get(i);
//			double value = Double.parseDouble(obj[1].toString());
////			double value = this.adjustData(maxAverageClosePrice, minAverageClosePrice, maxMa5, minMa5, Double.parseDouble(obj[1].toString()));
//			averageCloseSeries.add(new Day(day, month, year), value);
//		}

        timeSeriesCollection.addSeries(closePriceSeries);
        timeSeriesCollection.addSeries(ma5Series);
//		timeSeriesCollection.addSeries(averageCloseSeries);

        jfreechart = ChartFactory.createTimeSeriesChart("close_price Index & MA5 Index",
                "Date", "Index", timeSeriesCollection, true, true, true);
        jfreechart.setBackgroundPaint(Color.white);
        XYPlot xyplot = (XYPlot) jfreechart.getPlot();
        xyplot.setBackgroundPaint(Color.lightGray);
        xyplot.setDomainGridlinePaint(Color.white);
        xyplot.setRangeGridlinePaint(Color.white);
        xyplot.setAxisOffset(new RectangleInsets(5D, 5D, 5D, 5D));
        xyplot.setDomainCrosshairVisible(true);
        xyplot.setRangeCrosshairVisible(true);
        org.jfree.chart.renderer.xy.XYItemRenderer xyitemrenderer = xyplot.getRenderer();
        if (xyitemrenderer instanceof XYLineAndShapeRenderer) {
            XYLineAndShapeRenderer xylineandshaperenderer = (XYLineAndShapeRenderer) xyitemrenderer;
            xylineandshaperenderer.setBaseShapesVisible(true);
            xylineandshaperenderer.setBaseShapesFilled(true);
            xylineandshaperenderer.setSeriesPaint(2, Color.BLACK);
        }
        DateAxis dateaxis = (DateAxis) xyplot.getDomainAxis();
        dateaxis.setDateFormatOverride(new SimpleDateFormat("yyyy-MM-dd"));

        try {
            FileOutputStream fos = new FileOutputStream(PICTURE_PATH + "close_price_gold_cross_ma5/" + closePriceGoldCrossMa5BeginDate + "-" + closePriceGoldCrossMa5EndDate + PICTURE_FORMAT);
            // 将统计图标输出成JPG文件
            ChartUtilities.writeChartAsJPEG(fos, // 输出到哪个输出流
                    1, // JPEG图片的质量，0~1之间
                    jfreechart, // 统计图标对象
                    imageWidth, // 宽
                    IMAGE_HEIGHT, // 高
                    null // ChartRenderingInfo 信息
            );
            fos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 创建hei_kin_ashi上升趋势图
     *
     * @param multithreading
     */
    public void createHeiKinAshiUpDownPicture(boolean multithreading) {
        logger.info("开始创建hei_kin_ashi上升趋势的图表");

        String heiKinAshiUpDownBeginDate = PropertiesUtil.getValue(STOCK_RECORD_PICTURE_PROPERTIES, "stockRecordPicture.heiKinAshi.upDown.beginDate");
        String heiKinAshiUpDownEndDate = PropertiesUtil.getValue(STOCK_RECORD_PICTURE_PROPERTIES, "stockRecordPicture.heiKinAshi.upDown.endDate");

        // 获取数据
        List<String> dateList = stockTransactionDataDao.findDistinctDateBetweenDate(multithreading, heiKinAshiUpDownBeginDate, heiKinAshiUpDownEndDate);
        JFreeChart jfreechart;

        // 获取某一段时间内平均价格中的最大价格和最小价格
//		List maxMinCloseList = stockTransactionDataDao.getMaxMinAverageCloseWeek(multithreading, heiKinAshiUpDownBeginDate, heiKinAshiUpDownEndDate);
//		double maxClose = Double.parseDouble(((Object[]) maxMinCloseList.get(0))[0].toString());
//		double minClose = Double.parseDouble(((Object[]) maxMinCloseList.get(0))[1].toString());
        // 获取某一段时间内ha_close_price和ha_open_price的最大值和最小值
//		List maxMinHaClosePriceAndHaOpenPriceList = stockTransactionDataDao.getMaxMinHaClosePriceAndHaOpenPrice(multithreading, heiKinAshiUpDownBeginDate, heiKinAshiUpDownEndDate);
//		double maxHaClosePrice = Double.parseDouble(((Object[]) maxMinHaClosePriceAndHaOpenPriceList.get(0))[0].toString());
//		double minHaClosePrice = Double.parseDouble(((Object[]) maxMinHaClosePriceAndHaOpenPriceList.get(0))[1].toString());
//		double maxHaOpenPrice = Double.parseDouble(((Object[]) maxMinHaClosePriceAndHaOpenPriceList.get(0))[2].toString());
//		double minHaOpenPrice = Double.parseDouble(((Object[]) maxMinHaClosePriceAndHaOpenPriceList.get(0))[3].toString());

//		List averageAllCloseList = stockTransactionDataDao.getAverageCloseWithDate(multithreading, heiKinAshiUpDownBeginDate, heiKinAshiUpDownEndDate, false, "all");
        TimeSeries haClosePriceSeries = new TimeSeries("ha_close_price Index", org.jfree.data.time.Day.class);
        TimeSeries haOpenPriceSeries = new TimeSeries("ha_open_price Index", org.jfree.data.time.Day.class);
//		TimeSeries averageCloseSeries = new TimeSeries("Average Stock Close", org.jfree.data.time.Day.class);
        TimeSeriesCollection timeSeriesCollection = new TimeSeriesCollection();

        for (int i = 0; i < dateList.size(); i++) {
            String[] str = dateList.get(i).toString().split("-");
            int year = Integer.parseInt(str[0]);
            int month = Integer.parseInt(str[1]);
            int day = Integer.parseInt(str[2]);
            double value = Double.valueOf(stockTransactionDataDao.getAverageHaClosePrice(multithreading, dateList.get(i).replace("-", "")));
            haClosePriceSeries.add(new Day(day, month, year), value);
        }
        for (int i = 0; i < dateList.size(); i++) {
            String[] str = dateList.get(i).toString().split("-");
            int year = Integer.parseInt(str[0]);
            int month = Integer.parseInt(str[1]);
            int day = Integer.parseInt(str[2]);
            double value = Double.valueOf(stockTransactionDataDao.getAverageHaOpenPrice(multithreading, dateList.get(i).replace("-", "")));
            haOpenPriceSeries.add(new Day(day, month, year), value);
        }
//		for (int i = 0; i < dateList.size(); i++) {
//			String[] str = dateList.get(i).toString().split("-");
//			int year = Integer.parseInt(str[0]);
//			int month = Integer.parseInt(str[1]);
//			int day = Integer.parseInt(str[2]);
//			Object[] obj = (Object[]) averageAllCloseList.get(i);
//			double value = this.adjustData(maxClose, minClose, maxHaClosePrice, minHaClosePrice, Double.parseDouble(obj[1].toString()));
//			averageCloseSeries.add(new Day(day, month, year), value);
//		}

        timeSeriesCollection.addSeries(haClosePriceSeries);
        timeSeriesCollection.addSeries(haOpenPriceSeries);
//		timeSeriesCollection.addSeries(averageCloseSeries);

        jfreechart = ChartFactory.createTimeSeriesChart("ha_close_price Index & ha_open_price Index",
                "Date", "Index", timeSeriesCollection, true, true, true);
        jfreechart.setBackgroundPaint(Color.white);
        XYPlot xyplot = (XYPlot) jfreechart.getPlot();
        xyplot.setBackgroundPaint(Color.lightGray);
        xyplot.setDomainGridlinePaint(Color.white);
        xyplot.setRangeGridlinePaint(Color.white);
        xyplot.setAxisOffset(new RectangleInsets(5D, 5D, 5D, 5D));
        xyplot.setDomainCrosshairVisible(true);
        xyplot.setRangeCrosshairVisible(true);
        org.jfree.chart.renderer.xy.XYItemRenderer xyitemrenderer = xyplot.getRenderer();
        if (xyitemrenderer instanceof XYLineAndShapeRenderer) {
            XYLineAndShapeRenderer xylineandshaperenderer = (XYLineAndShapeRenderer) xyitemrenderer;
            xylineandshaperenderer.setBaseShapesVisible(true);
            xylineandshaperenderer.setBaseShapesFilled(true);
            xylineandshaperenderer.setSeriesPaint(2, Color.BLACK);
        }
        DateAxis dateaxis = (DateAxis) xyplot.getDomainAxis();
        dateaxis.setDateFormatOverride(new SimpleDateFormat("yyyy-MM-dd"));

        try {
            FileOutputStream fos = new FileOutputStream(PICTURE_PATH + "hei_kin_ashi_up_down/" + heiKinAshiUpDownBeginDate + "-" + heiKinAshiUpDownEndDate + PICTURE_FORMAT);
            // 将统计图标输出成JPG文件
            ChartUtilities.writeChartAsJPEG(fos, // 输出到哪个输出流
                    1, // JPEG图片的质量，0~1之间
                    jfreechart, // 统计图标对象
                    imageWidth, // 宽
                    IMAGE_HEIGHT, // 高
                    null // ChartRenderingInfo 信息
            );
            fos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 据开始日期和结束日期，创建股票收盘价图图。分别用来创建最近10年的图和半年的图
     *
     * @param multithreading
     * @param beginDate      开始时间
     * @param endDate        结束时间
     * @param flag           创建最近10年图时，flag为true，图片名称中有all；创建半年图时，flag为false，图片名称中没有all
     */
    public void paintClosePicture(boolean multithreading, String beginDate, String endDate, boolean flag) {
        TimeSeriesCollection timeSeriesCollection = new TimeSeriesCollection();

        // 获取上证指数从开始日期至结束日期的所有交易日
        List<String> allDateList = stockTransactionDataDao.getDateByConditionForClose(multithreading, beginDate, endDate, IndexInfo.SH_INDEX.getCode());
        // 获取所有A股从开始日期至结束日期的所有交易数据
        List averageAllCloseList = stockTransactionDataDao.getAverageCloseWithDate(multithreading, beginDate, endDate, flag, "all");
        TimeSeries allCloseSeries = new TimeSeries("All Stock Close", org.jfree.data.time.Day.class);
        for (int i = 0, j = 0; i < allDateList.size() && j < averageAllCloseList.size(); ) {// 此处用上证指数来代替
            /* 因为有时候有的板块可能所有股票都停牌，如2015年7月14日中小板和创业板，因此要做下面的判断 。
             * 如果某个板块某个交易日全部停牌，则那天的线图上没有那个点
             * 注意有时候STOCK_INDEX表中没有记录，但STOCK_TRANSACTION_DATA表中却有记录*/
            Date allDateListDate = DateUtil.stringToDate(allDateList.get(i).toString().replace("-", ""));
            Date averageAllCloseListDate = DateUtil.stringToDate(((Object[]) averageAllCloseList.get(j))[0].toString().replace("-", ""));
            if (allDateListDate.equals(averageAllCloseListDate)) {
                String[] str = allDateList.get(i).toString().split("-");
                int year = Integer.parseInt(str[0]);
                int month = Integer.parseInt(str[1]);
                int day = Integer.parseInt(str[2]);
                Object[] obj = (Object[]) averageAllCloseList.get(j);
                double value = Double.parseDouble(obj[1].toString());
                allCloseSeries.add(new Day(day, month, year), value);
                i++;
                j++;
            } else if (allDateListDate.before(averageAllCloseListDate)) {
                String[] str = allDateList.get(i).toString().split("-");
                int year = Integer.parseInt(str[0]);
                int month = Integer.parseInt(str[1]);
                int day = Integer.parseInt(str[2]);
                allCloseSeries.add(new Day(day, month, year), null);
                i++;
            } else {
                Object[] obj = (Object[]) averageAllCloseList.get(j);
                int year = DateUtil.getYearFromDate((Date) obj[0]);
                int month = DateUtil.getMonthFromDate((Date) obj[0]);
                int day = DateUtil.getDateFromDate((Date) obj[0]);
                allCloseSeries.add(new Day(day, month, year), null);
                j++;
            }
        }
        timeSeriesCollection.addSeries(allCloseSeries);

        // 获取上证指数从开始日期至结束日期的所有交易日
        List<String> shDateList = stockTransactionDataDao.getDateByConditionForClose(multithreading, beginDate, endDate, IndexInfo.SH_INDEX.getCode());
        // 获取沪深A股和科创版所有股票从开始日期至结束日期的所有交易数据
        List averageShCloseList = stockTransactionDataDao.getAverageCloseWithDate(multithreading, beginDate, endDate, flag, ExchangeBoardInfo.SH_PREFIX.getCodePrefixArray());
        TimeSeries shCloseSeries = new TimeSeries("SH Stock Close", org.jfree.data.time.Day.class);
        for (int i = 0, j = 0; i < shDateList.size() && j < averageShCloseList.size(); ) {
            Date shDateListDate = DateUtil.stringToDate(shDateList.get(i).toString().replace("-", ""));
            Date averageShCloseListDate = DateUtil.stringToDate(((Object[]) averageShCloseList.get(j))[0].toString().replace("-", ""));
            if (shDateListDate.equals(averageShCloseListDate)) {
                String[] str = shDateList.get(i).toString().split("-");
                int year = Integer.parseInt(str[0]);
                int month = Integer.parseInt(str[1]);
                int day = Integer.parseInt(str[2]);
                Object[] obj = (Object[]) averageShCloseList.get(j);
                double value = Double.parseDouble(obj[1].toString());
                shCloseSeries.add(new Day(day, month, year), value);
                i++;
                j++;
            } else if (shDateListDate.before(averageShCloseListDate)) {
                String[] str = shDateList.get(i).toString().split("-");
                int year = Integer.parseInt(str[0]);
                int month = Integer.parseInt(str[1]);
                int day = Integer.parseInt(str[2]);
                shCloseSeries.add(new Day(day, month, year), null);
                i++;
            } else {
                Object[] obj = (Object[]) averageShCloseList.get(j);
                int year = DateUtil.getYearFromDate((Date) obj[0]);
                int month = DateUtil.getMonthFromDate((Date) obj[0]);
                int day = DateUtil.getDateFromDate((Date) obj[0]);
                shCloseSeries.add(new Day(day, month, year), null);
                j++;
            }
        }
        timeSeriesCollection.addSeries(shCloseSeries);

        // 获取深证成指从开始日期至结束日期的所有交易日
        List<String> szDateList = stockTransactionDataDao.getDateByConditionForClose(multithreading, beginDate, endDate, IndexInfo.SZ_INDEX.getCode());
        // 获取深市A股所有股票从开始日期至结束日期的所有交易数据
        List averageSzCloseList = stockTransactionDataDao.getAverageCloseWithDate(multithreading, beginDate, endDate, flag, ExchangeBoardInfo.SZ_PREFIX.getCodePrefixArray());
        TimeSeries szCloseSeries = new TimeSeries("SZ Stock Close", org.jfree.data.time.Day.class);
        for (int i = 0, j = 0; i < szDateList.size() && j < averageSzCloseList.size(); ) {
            Date szDateListDate = DateUtil.stringToDate(szDateList.get(i).toString().replace("-", ""));
            Date averageSzCloseListDate = DateUtil.stringToDate(((Object[]) averageSzCloseList.get(j))[0].toString().replace("-", ""));
            if (szDateListDate.equals(averageSzCloseListDate)) {
                String[] str = szDateList.get(i).toString().split("-");
                int year = Integer.parseInt(str[0]);
                int month = Integer.parseInt(str[1]);
                int day = Integer.parseInt(str[2]);
                Object[] obj = (Object[]) averageSzCloseList.get(j);
                double value = Double.parseDouble(obj[1].toString());
                szCloseSeries.add(new Day(day, month, year), value);
                i++;
                j++;
            } else if (szDateListDate.before(averageSzCloseListDate)) {
                String[] str = szDateList.get(i).toString().split("-");
                int year = Integer.parseInt(str[0]);
                int month = Integer.parseInt(str[1]);
                int day = Integer.parseInt(str[2]);
                szCloseSeries.add(new Day(day, month, year), null);
                i++;
            } else {
                Object[] obj = (Object[]) averageSzCloseList.get(j);
                int year = DateUtil.getYearFromDate((Date) obj[0]);
                int month = DateUtil.getMonthFromDate((Date) obj[0]);
                int day = DateUtil.getDateFromDate((Date) obj[0]);
                szCloseSeries.add(new Day(day, month, year), null);
                j++;
            }
        }
        timeSeriesCollection.addSeries(szCloseSeries);

        // 获取中小板指数从开始日期至结束日期的所有交易日
        List<String> zxbDateList = stockTransactionDataDao.getDateByConditionForClose(multithreading, beginDate, endDate, IndexInfo.ZXB_INDEX.getCode());
        // 获取中小板所有股票从开始日期至结束日期的所有交易数据
        List averageZxbCloseList = stockTransactionDataDao.getAverageCloseWithDate(multithreading, beginDate, endDate, flag, ExchangeBoardInfo.ZXB_PREFIX.getCodePrefixArray());
        TimeSeries zxbCloseSeries = new TimeSeries("ZXB Stock Close", org.jfree.data.time.Day.class);
        for (int i = 0, j = 0; i < zxbDateList.size() && j < averageZxbCloseList.size(); ) {
            Date zxbDateListDate = DateUtil.stringToDate(zxbDateList.get(i).toString().replace("-", ""));
            Date averageZxbCloseListDate = DateUtil.stringToDate(((Object[]) averageZxbCloseList.get(j))[0].toString().replace("-", ""));
            if (zxbDateListDate.equals(averageZxbCloseListDate)) {
                String[] str = zxbDateList.get(i).toString().split("-");
                int year = Integer.parseInt(str[0]);
                int month = Integer.parseInt(str[1]);
                int day = Integer.parseInt(str[2]);
                Object[] obj = (Object[]) averageZxbCloseList.get(j);
                double value = Double.parseDouble(obj[1].toString());
                zxbCloseSeries.add(new Day(day, month, year), value);
                i++;
                j++;
            } else if (zxbDateListDate.before(averageZxbCloseListDate)) {
                String[] str = zxbDateList.get(i).toString().split("-");
                int year = Integer.parseInt(str[0]);
                int month = Integer.parseInt(str[1]);
                int day = Integer.parseInt(str[2]);
                zxbCloseSeries.add(new Day(day, month, year), null);
                i++;
            } else {
                Object[] obj = (Object[]) averageZxbCloseList.get(j);
                int year = DateUtil.getYearFromDate((Date) obj[0]);
                int month = DateUtil.getMonthFromDate((Date) obj[0]);
                int day = DateUtil.getDateFromDate((Date) obj[0]);
                zxbCloseSeries.add(new Day(day, month, year), null);
                j++;
            }
        }
        timeSeriesCollection.addSeries(zxbCloseSeries);

        // 获取创业板指数从开始日期至结束日期的所有交易日
        List<String> cybDateList = stockTransactionDataDao.getDateByConditionForClose(multithreading, beginDate, endDate, IndexInfo.CYB_INDEX.getCode());
        // 获取创业板所有股票从开始日期至结束日期的所有交易数据
        List averageCybCloseList = stockTransactionDataDao.getAverageCloseWithDate(multithreading, beginDate, endDate, flag, ExchangeBoardInfo.CYB_PREFIX.getCodePrefixArray());
        TimeSeries cybCloseSeries = new TimeSeries("CYB Stock Close", org.jfree.data.time.Day.class);
        for (int i = 0, j = 0; i < cybDateList.size() && j < averageCybCloseList.size(); ) {
            Date cybDateListDate = DateUtil.stringToDate(cybDateList.get(i).toString().replace("-", ""));
            Date averageCybCloseListDate = DateUtil.stringToDate(((Object[]) averageCybCloseList.get(j))[0].toString().replace("-", ""));
            if (cybDateListDate.equals(averageCybCloseListDate)) {
                String[] str = cybDateList.get(i).toString().split("-");
                int year = Integer.parseInt(str[0]);
                int month = Integer.parseInt(str[1]);
                int day = Integer.parseInt(str[2]);
                Object[] obj = (Object[]) averageCybCloseList.get(j);
                double value = Double.parseDouble(obj[1].toString());
                cybCloseSeries.add(new Day(day, month, year), value);
                i++;
                j++;
            } else if (cybDateListDate.before(averageCybCloseListDate)) {
                String[] str = cybDateList.get(i).toString().split("-");
                int year = Integer.parseInt(str[0]);
                int month = Integer.parseInt(str[1]);
                int day = Integer.parseInt(str[2]);
                cybCloseSeries.add(new Day(day, month, year), null);
                i++;
            } else {
                Object[] obj = (Object[]) averageCybCloseList.get(j);
                int year = DateUtil.getYearFromDate((Date) obj[0]);
                int month = DateUtil.getMonthFromDate((Date) obj[0]);
                int day = DateUtil.getDateFromDate((Date) obj[0]);
                cybCloseSeries.add(new Day(day, month, year), null);
                j++;
            }
        }
        timeSeriesCollection.addSeries(cybCloseSeries);

        JFreeChart jfreechart = ChartFactory.createTimeSeriesChart("Stock Close",
                "Date", "Stock Close", timeSeriesCollection, true, true, true);
        jfreechart.setBackgroundPaint(Color.white);
        XYPlot xyplot = (XYPlot) jfreechart.getPlot();
        xyplot.setBackgroundPaint(Color.lightGray);
        xyplot.setDomainGridlinePaint(Color.white);
        xyplot.setRangeGridlinePaint(Color.white);
        xyplot.setAxisOffset(new RectangleInsets(5D, 5D, 5D, 5D));
        xyplot.setDomainCrosshairVisible(true);
        xyplot.setRangeCrosshairVisible(true);
        org.jfree.chart.renderer.xy.XYItemRenderer xyitemrenderer = xyplot.getRenderer();
        if (xyitemrenderer instanceof XYLineAndShapeRenderer) {
            XYLineAndShapeRenderer xylineandshaperenderer = (XYLineAndShapeRenderer) xyitemrenderer;
            xylineandshaperenderer.setBaseShapesVisible(true);
            xylineandshaperenderer.setBaseShapesFilled(true);
        }
        DateAxis dateaxis = (DateAxis) xyplot.getDomainAxis();
        dateaxis.setDateFormatOverride(new SimpleDateFormat("yyyy-MM-dd"));

        try {
            FileOutputStream fos = new FileOutputStream(PICTURE_PATH + "close/" + beginDate + "-" + endDate + (flag ? "_all" : "") + PICTURE_FORMAT);
            // 将统计图标输出成JPG文件
            ChartUtilities.writeChartAsJPEG(fos, // 输出到哪个输出流
                    1, // JPEG图片的质量，0~1之间
                    jfreechart, // 统计图标对象
                    imageWidth, // 宽
                    IMAGE_HEIGHT, // 高
                    null // ChartRenderingInfo 信息
            );
            fos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
		
		
		
		/*// 获取上证指数从开始日期至结束日期的所有交易日
		List<String> dateList = stockTransactionDataDao.getDateByConditionForClose(beginDate, endDate);
		JFreeChart jfreechart;
		
		List averageCloseList=stockTransactionDataDao.getAverageCloseWithDate(beginDate, endDate);

		TimeSeries closeSeries = new TimeSeries("Stock Close",org.jfree.data.time.Day.class);
		TimeSeriesCollection timeSeriesCollection = new TimeSeriesCollection();
		for (int i = 0; i < dateList.size(); i++) {
			String[] str = dateList.get(i).toString().split("-");
			int year = Integer.parseInt(str[0]);
			int month = Integer.parseInt(str[1]);
			int day = Integer.parseInt(str[2]);
			Object[] obj=(Object[]) averageCloseList.get(i);
			closeSeries.add(new Day(day, month, year),Double.parseDouble(obj[1].toString()));
		}
		
		timeSeriesCollection.addSeries(closeSeries);

		jfreechart = ChartFactory.createTimeSeriesChart("Stock Close", 
				"Date","Stock Close", timeSeriesCollection, true, true, true);
		jfreechart.setBackgroundPaint(Color.white);
		XYPlot xyplot = (XYPlot) jfreechart.getPlot();
		xyplot.setBackgroundPaint(Color.lightGray);
		xyplot.setDomainGridlinePaint(Color.white);
		xyplot.setRangeGridlinePaint(Color.white);
		xyplot.setAxisOffset(new RectangleInsets(5D, 5D, 5D, 5D));
		xyplot.setDomainCrosshairVisible(true);
		xyplot.setRangeCrosshairVisible(true);
		org.jfree.chart.renderer.xy.XYItemRenderer xyitemrenderer = xyplot.getRenderer();
		if (xyitemrenderer instanceof XYLineAndShapeRenderer) {
			XYLineAndShapeRenderer xylineandshaperenderer = (XYLineAndShapeRenderer) xyitemrenderer;
			xylineandshaperenderer.setBaseShapesVisible(true);
			xylineandshaperenderer.setBaseShapesFilled(true);
		}
		DateAxis dateaxis = (DateAxis) xyplot.getDomainAxis();
		dateaxis.setDateFormatOverride(new SimpleDateFormat("yyyy-MM-dd"));

		try {
			FileOutputStream fos = new FileOutputStream(PICTURE_PATH+"close/"+beginDate+"-"+endDate+(flag?"_all":"")+PICTURE_FORMAT);
			// 将统计图标输出成JPG文件
			ChartUtilities.writeChartAsJPEG(fos, // 输出到哪个输出流
					1, // JPEG图片的质量，0~1之间
					jfreechart, // 统计图标对象
					1800, // 宽
					1000,// 宽
					null // ChartRenderingInfo 信息
					);
			fos.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}*/
    }

    /**
     * 创建28分化图表
     */
    @SuppressWarnings("deprecation")
    public void createDifferentiationPicture(boolean multithreading) {
        //获取开始时间和结束时间
        String beginDateForLineChart = PropertiesUtil.getValue(STOCK_RECORD_PICTURE_PROPERTIES, "stockRecordPicture.28.beginDate");
        String endDateForLineChart = PropertiesUtil.getValue(STOCK_RECORD_PICTURE_PROPERTIES, "stockRecordPicture.28.endDate");

        //设置字体样式，解决中文乱码问题
        //创建主题样式
        StandardChartTheme standardChartTheme = new StandardChartTheme("CN");
        //设置标题字体
        standardChartTheme.setExtraLargeFont(new Font("隶书", Font.BOLD, 20));
        //设置图例的字体
        standardChartTheme.setRegularFont(new Font("宋书", Font.PLAIN, 15));
        //设置轴向的字体
        standardChartTheme.setLargeFont(new Font("宋书", Font.PLAIN, 15));
        //应用主题样式
        ChartFactory.setChartTheme(standardChartTheme);

        JFreeChart lineChart = ChartFactory.createLineChart(
                "28 differentiation picture",       // chart title
                "date",                    // domain axis label
                "index",                   // range axis label
                this.getLineDataSet(multithreading),                   // data
                PlotOrientation.VERTICAL,  // orientation
                true,                      // include legend
                true,                      // tooltips
                false                      // urls
        );

        JFreeChart barchart = ChartFactory.createBarChart3D(
                "28 differentiation picture",
                "date",//目录轴的显示标签
                "the number of up and down",//数值轴的显示标签
                this.getBarDataSet(multithreading),
                PlotOrientation.VERTICAL,//设置图表方向
                true,//复杂柱状图
                false,
                false
        );

        CategoryPlot plot = lineChart.getCategoryPlot();  //关键位置

        NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
        rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
        rangeAxis.setAutoRangeIncludesZero(true);
        rangeAxis.setUpperMargin(0.05);
        rangeAxis.setLabelAngle(Math.PI / 2.0);

        LineAndShapeRenderer renderer = (LineAndShapeRenderer) plot.getRenderer();
        renderer.setShape(new Rectangle2D.Double(-1.5, -1.5, 3, 3));
        renderer.setShapesVisible(true);
        renderer.setSeriesPaint(3, Color.red);
        renderer.setSeriesLinesVisible(3, false);

        renderer.setItemLabelGenerator(new StandardCategoryItemLabelGenerator());//显示折点数据
        renderer.setItemLabelsVisible(true);

        CategoryPlot barplot = barchart.getCategoryPlot();  //关键位置
        plot.setDataset(1, this.getBarDataSet(multithreading));
        plot.setRenderer(1, barplot.getRenderer());

        try {
            FileOutputStream fos = new FileOutputStream(PICTURE_PATH + "28_differentiation/" + beginDateForLineChart + "-" + endDateForLineChart + PICTURE_FORMAT);
            // 将统计图标输出成JPG文件
            ChartUtilities.writeChartAsJPEG(fos, // 输出到哪个输出流
                    1, // JPEG图片的质量，0~1之间
                    lineChart, // 统计图标对象
                    imageWidth, // 宽
                    IMAGE_HEIGHT, // 高
                    null // ChartRenderingInfo 信息
            );
            fos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取线图数据集DataSet
     *
     * @param multithreading
     * @return
     */
    public DefaultCategoryDataset getLineDataSet(boolean multithreading) {
        //获取开始时间和结束时间
        String beginDateForLineChart = PropertiesUtil.getValue(STOCK_RECORD_PICTURE_PROPERTIES, "stockRecordPicture.28.beginDate");
        String endDateForLineChart = PropertiesUtil.getValue(STOCK_RECORD_PICTURE_PROPERTIES, "stockRecordPicture.28.endDate");

        //上证指数
        List<StockIndex> shIndexLineChartList = stockIndexDao.getDataForLineChart(multithreading, beginDateForLineChart, endDateForLineChart, IndexInfo.SH_INDEX.getCode());
        //深证成指
        List<StockIndex> szIndexLineChartList = stockIndexDao.getDataForLineChart(multithreading, beginDateForLineChart, endDateForLineChart, IndexInfo.SZ_INDEX.getCode());
        //中小板指数
        List<StockIndex> zxbIndexLineChartList = stockIndexDao.getDataForLineChart(multithreading, beginDateForLineChart, endDateForLineChart, IndexInfo.ZXB_INDEX.getCode());
        //创业板指数
        List<StockIndex> cybIndexLineChartList = stockIndexDao.getDataForLineChart(multithreading, beginDateForLineChart, endDateForLineChart, IndexInfo.CYB_INDEX.getCode());


        //建立dataset
        DefaultCategoryDataset dataset = new DefaultCategoryDataset();
        for (int i = 0; i < shIndexLineChartList.size(); i++) {
            dataset.addValue(shIndexLineChartList.get(i).getClosePrice(), IndexInfo.SH_INDEX.getName(), shIndexLineChartList.get(i).getDate());
        }
//		for(int i=0;i<scIndexLineChartList.size();i++){
//			dataset.addValue(scIndexLineChartList.get(i).getIndexClose(), IndexInfo.SC_INDEX.getName(), scIndexLineChartList.get(i).getIndexDate());
//		}
//		for(int i=0;i<zxbIndexLineChartList.size();i++){
//			dataset.addValue(zxbIndexLineChartList.get(i).getIndexClose(), IndexInfo.ZXB_INDEX.getName(), zxbIndexLineChartList.get(i).getIndexDate());
//		}
//		for(int i=0;i<cybIndexLineChartList.size();i++){
//			dataset.addValue(cybIndexLineChartList.get(i).getIndexClose(), IndexInfo.CYB_INDEX.getName(), cybIndexLineChartList.get(i).getIndexDate());
//		}

        return dataset;
    }

    /**
     * 获取柱状图数据集DataSet
     *
     * @param multithreading
     * @return
     */
    public DefaultCategoryDataset getBarDataSet(boolean multithreading) {
        //获取开始时间和结束时间
        String beginDateForLineChart = PropertiesUtil.getValue(STOCK_RECORD_PICTURE_PROPERTIES, "stockRecordPicture.28.beginDate");
        String endDateForLineChart = PropertiesUtil.getValue(STOCK_RECORD_PICTURE_PROPERTIES, "stockRecordPicture.28.endDate");

        //获取交易日期集合
        List<Date> dateList = stockIndexDao.getDateForBarChart(multithreading, beginDateForLineChart, endDateForLineChart);

        //建立dataset
        DefaultCategoryDataset dataset = new DefaultCategoryDataset();
        for (int i = 0; i < dateList.size(); i++) {
            dataset.addValue(stockTransactionDataDao.getUpDownNumberForBarChart(multithreading, DateUtil.dateToString(dateList.get(i)), UpDown.UP), UpDown.UP.getDescription(), DateUtil.dateToString(dateList.get(i)));
            dataset.addValue(stockTransactionDataDao.getUpDownNumberForBarChart(multithreading, DateUtil.dateToString(dateList.get(i)), UpDown.DOWN), UpDown.DOWN.getDescription(), DateUtil.dateToString(dateList.get(i)));
        }

        return dataset;
    }

    /**
     * 创建股票涨停跌停数量图（折线图）
     *
     * @param multithreading
     */
    public void createStockLimitUpAndDownPicture(boolean multithreading) {
        String beginDate = PropertiesUtil.getValue(STOCK_RECORD_PICTURE_PROPERTIES, "stockRecordPicture.limitUpDown.beginDate");
        String endDate = PropertiesUtil.getValue(STOCK_RECORD_PICTURE_PROPERTIES, "stockRecordPicture.limitUpDown.endDate");

        JFreeChart jfreechart;
        jfreechart = ChartFactory.createTimeSeriesChart("Stock Up Down Number",
                "Date", "Number", this.getDatasetForStockLimitUpAndDownPicture(multithreading), true, true, true);
        jfreechart.setBackgroundPaint(Color.white);
        XYPlot xyplot = (XYPlot) jfreechart.getPlot();
        xyplot.setBackgroundPaint(Color.lightGray);
        xyplot.setDomainGridlinePaint(Color.white);
        xyplot.setRangeGridlinePaint(Color.white);
        xyplot.setAxisOffset(new RectangleInsets(5D, 5D, 5D, 5D));
        xyplot.setDomainCrosshairVisible(true);
        xyplot.setRangeCrosshairVisible(true);
        org.jfree.chart.renderer.xy.XYItemRenderer xyitemrenderer = xyplot.getRenderer();
        if (xyitemrenderer instanceof XYLineAndShapeRenderer) {
            XYLineAndShapeRenderer xylineandshaperenderer = (XYLineAndShapeRenderer) xyitemrenderer;
            xylineandshaperenderer.setBaseShapesVisible(true);
            xylineandshaperenderer.setBaseShapesFilled(true);
        }
        DateAxis dateaxis = (DateAxis) xyplot.getDomainAxis();
        dateaxis.setDateFormatOverride(new SimpleDateFormat("yyyy-MM-dd"));

        try {
            FileOutputStream fos = new FileOutputStream(PICTURE_PATH + "stock_up_down_limit_number/" + beginDate + "-" + endDate + PICTURE_FORMAT);
            // 将统计图标输出成JPG文件
            ChartUtilities.writeChartAsJPEG(fos, // 输出到哪个输出流
                    1, // JPEG图片的质量，0~1之间
                    jfreechart, // 统计图标对象
                    imageWidth, // 宽
                    IMAGE_HEIGHT, // 高
                    null // ChartRenderingInfo 信息
            );
            fos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 为创建股票涨跌停数量图（折线图）而获取数据
     *
     * @param multithreading
     * @return
     */
    @SuppressWarnings({"rawtypes", "deprecation"})
    public TimeSeriesCollection getDatasetForStockLimitUpAndDownPicture(boolean multithreading) {
        //获取开始时间，结束时间和涨跌率
        String beginDate = PropertiesUtil.getValue(STOCK_RECORD_PICTURE_PROPERTIES, "stockRecordPicture.limitUpDown.beginDate");
        String endDate = PropertiesUtil.getValue(STOCK_RECORD_PICTURE_PROPERTIES, "stockRecordPicture.limitUpDown.endDate");
        String positiveRate = PropertiesUtil.getValue(STOCK_RECORD_PICTURE_PROPERTIES, "stockRecordPicture.limitUpDown.positiveRate");
        String negativeRate = PropertiesUtil.getValue(STOCK_RECORD_PICTURE_PROPERTIES, "stockRecordPicture.limitUpDown.negativeRate");

        List stockUpList = null;
        List stockDownList = null;

        TimeSeries stockUpSeries = new TimeSeries("Stock Up", org.jfree.data.time.Day.class);
        TimeSeries stockDownSeries = new TimeSeries("Stock Down", org.jfree.data.time.Day.class);
        TimeSeriesCollection timeSeriesCollection = new TimeSeriesCollection();

        List<String> dateList = stockTransactionDataDao.getDateByCondition(multithreading, beginDate, endDate, false);
        stockUpList = stockTransactionDataDao.getStockLimitUpAndDownNumber(multithreading, beginDate, endDate, Double.parseDouble(positiveRate));
        stockDownList = stockTransactionDataDao.getStockLimitUpAndDownNumber(multithreading, beginDate, endDate, Double.parseDouble(negativeRate));

//		System.out.println(stockUpList.size());
//		System.out.println(stockDownList.size());

        // 注意：此处的情况和paintMovingAverageBullRankShortOrderPicture方法中的两个for一样
        for (int i = 0, j = 0; i < dateList.size() && j < stockUpList.size(); ) {
            String[] str = dateList.get(i).toString().split("-");
            int year = Integer.parseInt(str[0]);
            int month = Integer.parseInt(str[1]);
            int day = Integer.parseInt(str[2]);
            Object[] obj = (Object[]) stockUpList.get(j);
            if (dateList.get(i).toString().equals(obj[0].toString().split(" ")[0])) {
                stockUpSeries.add(new Day(day, month, year), Double.valueOf(obj[1].toString()));
                i++;
                j++;
            } else {
                stockUpSeries.add(new Day(day, month, year), 0);
                i++;
            }
        }
        for (int i = 0, j = 0; i < dateList.size() && j < stockDownList.size(); ) {
            String[] str = dateList.get(i).toString().split("-");
            int year = Integer.parseInt(str[0]);
            int month = Integer.parseInt(str[1]);
            int day = Integer.parseInt(str[2]);
            Object[] obj = (Object[]) stockDownList.get(j);
            if (dateList.get(i).toString().equals(obj[0].toString().split(" ")[0])) {
                stockDownSeries.add(new Day(day, month, year), Double.valueOf(obj[1].toString()));
                i++;
                j++;
            } else {
                stockDownSeries.add(new Day(day, month, year), 0);
                i++;
            }
        }

        timeSeriesCollection.addSeries(stockUpSeries);
        timeSeriesCollection.addSeries(stockDownSeries);

        return timeSeriesCollection;
    }

    /**
     * 创建从开始日期至结束日期内MACD处于金叉状态（dif>dea）的股票的比率的图表
     *
     * @param multithreading
     */
    public void createMACDGoldCrossStockRatePicture(boolean multithreading) {
        logger.info("开始创建从开始日期至结束日期内MACD处于金叉状态（dif>dea）的股票的比率的图表");

        String beginDate = PropertiesUtil.getValue(STOCK_RECORD_PICTURE_PROPERTIES, "stockRecordPicture.MACD_gold_cross_stock_rate.beginDate");
        String endDate = PropertiesUtil.getValue(STOCK_RECORD_PICTURE_PROPERTIES, "stockRecordPicture.MACD_gold_cross_stock_rate.endDate");

        TimeSeries goldCrossSeries = new TimeSeries("MACD Gold Cross Percentage", org.jfree.data.time.Day.class);
        TimeSeriesCollection timeSeriesCollection = new TimeSeriesCollection();

        // 获取某一段时间内平均价格中的最大价格和最小价格
        List maxMinList = stockTransactionDataDao.getMaxMinAverageCloseWeek(multithreading, beginDate, endDate);
        double maxClose = Double.parseDouble(((Object[]) maxMinList.get(0))[0].toString());
        double minClose = Double.parseDouble(((Object[]) maxMinList.get(0))[1].toString());

        List dateList = stockTransactionDataDao.getMACDGoldCrossStockRate(multithreading, beginDate, endDate);
        for (int i = 0; i < dateList.size(); i++) {
            Object[] obj = (Object[]) dateList.get(i);
            Date date = (Date) obj[0];
            int year = DateUtil.getYearFromDate(date);
            int month = DateUtil.getMonthFromDate(date);
            int day = DateUtil.getDateFromDate(date);
            BigDecimal percentage = (BigDecimal) obj[1];
            goldCrossSeries.add(new Day(day, month, year), percentage.doubleValue());
        }
        timeSeriesCollection.addSeries(goldCrossSeries);

        List<String> allDateList = stockTransactionDataDao.getDateByConditionForClose(multithreading, beginDate, endDate, IndexInfo.SH_INDEX.getCode());
        List averageAllCloseList = stockTransactionDataDao.getAverageCloseWithDate(multithreading, beginDate, endDate, false, "all");
        TimeSeries allCloseSeries = new TimeSeries("All Stock Close", org.jfree.data.time.Day.class);
        for (int i = 0, j = 0; i < allDateList.size() && j < averageAllCloseList.size(); ) {// 此处用上证指数来代替
            /* 因为有时候有的板块可能所有股票都停牌，如2015年7月14日中小板和创业板，因此要做下面的判断 。
             * 如果某个板块某个交易日全部停牌，则那天的线图上没有那个点
             * 注意有时候STOCK_INDEX表中没有记录，但STOCK_MOVING_AVERAGE表中却有记录*/
            Date allDateListDate = DateUtil.stringToDate(allDateList.get(i).toString().replace("-", ""));
            Date averageAllCloseListDate = DateUtil.stringToDate(((Object[]) averageAllCloseList.get(j))[0].toString().replace("-", ""));
            if (allDateListDate.equals(averageAllCloseListDate)) {
                String[] str = allDateList.get(i).toString().split("-");
                int year = Integer.parseInt(str[0]);
                int month = Integer.parseInt(str[1]);
                int day = Integer.parseInt(str[2]);
                Object[] obj = (Object[]) averageAllCloseList.get(j);
                double value = Double.parseDouble(obj[1].toString());
                allCloseSeries.add(new Day(day, month, year), this.averageCloseAfterAdjust(value, maxClose, minClose));
                i++;
                j++;
            } else if (allDateListDate.before(averageAllCloseListDate)) {
                String[] str = allDateList.get(i).toString().split("-");
                int year = Integer.parseInt(str[0]);
                int month = Integer.parseInt(str[1]);
                int day = Integer.parseInt(str[2]);
                allCloseSeries.add(new Day(day, month, year), null);
                i++;
            } else {
                Object[] obj = (Object[]) averageAllCloseList.get(j);
                int year = DateUtil.getYearFromDate((Date) obj[0]);
                int month = DateUtil.getMonthFromDate((Date) obj[0]);
                int day = DateUtil.getDateFromDate((Date) obj[0]);
                allCloseSeries.add(new Day(day, month, year), null);
                j++;
            }
        }
        timeSeriesCollection.addSeries(allCloseSeries);

        JFreeChart jfreechart;
        jfreechart = ChartFactory.createTimeSeriesChart("MACD Gold Cross Percentage",
                "Date", "Gold Cross Percentage", timeSeriesCollection, true, true, true);
        jfreechart.setBackgroundPaint(Color.white);
        XYPlot xyplot = (XYPlot) jfreechart.getPlot();
        xyplot.setBackgroundPaint(Color.lightGray);
        xyplot.setDomainGridlinePaint(Color.white);
        xyplot.setRangeGridlinePaint(Color.white);
        xyplot.setAxisOffset(new RectangleInsets(5D, 5D, 5D, 5D));
        xyplot.setDomainCrosshairVisible(true);
        xyplot.setRangeCrosshairVisible(true);
        org.jfree.chart.renderer.xy.XYItemRenderer xyitemrenderer = xyplot.getRenderer();
        if (xyitemrenderer instanceof XYLineAndShapeRenderer) {
            XYLineAndShapeRenderer xylineandshaperenderer = (XYLineAndShapeRenderer) xyitemrenderer;
            xylineandshaperenderer.setBaseShapesVisible(true);
            xylineandshaperenderer.setBaseShapesFilled(true);
            xylineandshaperenderer.setSeriesPaint(2, Color.BLACK);
        }
        DateAxis dateaxis = (DateAxis) xyplot.getDomainAxis();
        dateaxis.setDateFormatOverride(new SimpleDateFormat("yyyy-MM-dd"));

        try {
            FileOutputStream fos = new FileOutputStream(PICTURE_PATH + "macd_gold_cross_percentage/" + beginDate + "-" + endDate + PICTURE_FORMAT);
            // 将统计图标输出成JPG文件
            ChartUtilities.writeChartAsJPEG(fos, // 输出到哪个输出流
                    1, // JPEG图片的质量，0~1之间
                    jfreechart, // 统计图标对象
                    imageWidth,// 宽
                    IMAGE_HEIGHT,// 高
                    null // ChartRenderingInfo 信息
            );
            fos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 创建上证股票，深证股票，中小板股票和创业板股票日线级别平均涨跌幅度图
     *
     * @param multithreading
     */
    @SuppressWarnings({"deprecation", "rawtypes"})
    public void createStockBigBoardUpDownPercentagePicture(boolean multithreading) {
        String beginDate = PropertiesUtil.getValue(STOCK_RECORD_PICTURE_PROPERTIES, "stockRecordPicture.stockBoard.upDown.percentage.beginDate");
        String endDate = PropertiesUtil.getValue(STOCK_RECORD_PICTURE_PROPERTIES, "stockRecordPicture.stockBoard.upDown.percentage.endDate");

        TimeSeriesCollection timeSeriesCollection = new TimeSeriesCollection();

        List shStockBigBoardUpDownPercentageList = stockTransactionDataDao.getStockBigBoardUpDownPercentage(multithreading, beginDate, endDate, "60%");
        List scStockBigBoardUpDownPercentageList = stockTransactionDataDao.getStockBigBoardUpDownPercentage(multithreading, beginDate, endDate, "000%");
        List zxbStockBigBoardUpDownPercentageList = stockTransactionDataDao.getStockBigBoardUpDownPercentage(multithreading, beginDate, endDate, "002%");
        List cybStockBigBoardUpDownPercentageList = stockTransactionDataDao.getStockBigBoardUpDownPercentage(multithreading, beginDate, endDate, "300%");

        // 上证股票涨跌百分比
        TimeSeries shStockBigBoardUpDownPercentage = new TimeSeries("SZ Stock Board Up Down Percentage", org.jfree.data.time.Day.class);
        for (int i = 0; i < shStockBigBoardUpDownPercentageList.size(); i++) {
            Object[] obj = (Object[]) shStockBigBoardUpDownPercentageList.get(i);
            String[] dateArray = obj[0].toString().split(" ")[0].split("-");
            int year = Integer.parseInt(dateArray[0]);
            int month = Integer.parseInt(dateArray[1]);
            int date = Integer.parseInt(dateArray[2]);
            double upDownPercentage = Double.parseDouble(obj[1].toString());
            shStockBigBoardUpDownPercentage.add(new Day(date, month, year), upDownPercentage);
        }
        timeSeriesCollection.addSeries(shStockBigBoardUpDownPercentage);

        // 深证股票涨跌百分比
        TimeSeries scStockBigBoardUpDownPercentage = new TimeSeries("SC Stock Board Up Down Percentage", org.jfree.data.time.Day.class);
        for (int i = 0; i < scStockBigBoardUpDownPercentageList.size(); i++) {
            Object[] obj = (Object[]) scStockBigBoardUpDownPercentageList.get(i);
            String[] dateArray = obj[0].toString().split(" ")[0].split("-");
            int year = Integer.parseInt(dateArray[0]);
            int month = Integer.parseInt(dateArray[1]);
            int date = Integer.parseInt(dateArray[2]);
            double upDownPercentage = Double.parseDouble(obj[1].toString());
            scStockBigBoardUpDownPercentage.add(new Day(date, month, year), upDownPercentage);
        }
        timeSeriesCollection.addSeries(scStockBigBoardUpDownPercentage);

        // 中小板股票涨跌百分比
        TimeSeries zxbStockBigBoardUpDownPercentage = new TimeSeries("ZXB Stock Board Up Down Percentage", org.jfree.data.time.Day.class);
        for (int i = 0; i < zxbStockBigBoardUpDownPercentageList.size(); i++) {
            Object[] obj = (Object[]) zxbStockBigBoardUpDownPercentageList.get(i);
            String[] dateArray = obj[0].toString().split(" ")[0].split("-");
            int year = Integer.parseInt(dateArray[0]);
            int month = Integer.parseInt(dateArray[1]);
            int date = Integer.parseInt(dateArray[2]);
            double upDownPercentage = Double.parseDouble(obj[1].toString());
            zxbStockBigBoardUpDownPercentage.add(new Day(date, month, year), upDownPercentage);
        }
        timeSeriesCollection.addSeries(zxbStockBigBoardUpDownPercentage);

        // 创业板股票涨跌百分比
        TimeSeries cybStockBigBoardUpDownPercentage = new TimeSeries("CYB Stock Board Up Down Percentage", org.jfree.data.time.Day.class);
        for (int i = 0; i < cybStockBigBoardUpDownPercentageList.size(); i++) {
            Object[] obj = (Object[]) cybStockBigBoardUpDownPercentageList.get(i);
            String[] dateArray = obj[0].toString().split(" ")[0].split("-");
            int year = Integer.parseInt(dateArray[0]);
            int month = Integer.parseInt(dateArray[1]);
            int date = Integer.parseInt(dateArray[2]);
            double upDownPercentage = Double.parseDouble(obj[1].toString());
            cybStockBigBoardUpDownPercentage.add(new Day(date, month, year), upDownPercentage);
        }
        timeSeriesCollection.addSeries(cybStockBigBoardUpDownPercentage);

        JFreeChart jfreechart = ChartFactory.createTimeSeriesChart("Stock Board Up Down Percentage",
                "Date", "Up Down Percentage", timeSeriesCollection, true, true, true);
        jfreechart.setBackgroundPaint(Color.white);
        XYPlot xyplot = (XYPlot) jfreechart.getPlot();
        xyplot.setBackgroundPaint(Color.lightGray);
        xyplot.setDomainGridlinePaint(Color.white);
        xyplot.setRangeGridlinePaint(Color.white);
        xyplot.setAxisOffset(new RectangleInsets(5D, 5D, 5D, 5D));
        xyplot.setDomainCrosshairVisible(true);
        xyplot.setRangeCrosshairVisible(true);
        org.jfree.chart.renderer.xy.XYItemRenderer xyitemrenderer = xyplot.getRenderer();
        if (xyitemrenderer instanceof XYLineAndShapeRenderer) {
            XYLineAndShapeRenderer xylineandshaperenderer = (XYLineAndShapeRenderer) xyitemrenderer;
            xylineandshaperenderer.setBaseShapesVisible(true);
            xylineandshaperenderer.setBaseShapesFilled(true);
        }
        DateAxis dateaxis = (DateAxis) xyplot.getDomainAxis();
        dateaxis.setDateFormatOverride(new SimpleDateFormat("yyyy-MM-dd"));

        try {
            FileOutputStream fos = new FileOutputStream(PICTURE_PATH + "stock_board_up_down_percentage/" + beginDate + "-" + endDate + PICTURE_FORMAT);
            // 将统计图标输出成JPG文件
            ChartUtilities.writeChartAsJPEG(fos, // 输出到哪个输出流
                    1, // JPEG图片的质量，0~1之间
                    jfreechart, // 统计图标对象
                    imageWidth, // 宽
                    IMAGE_HEIGHT, // 高
                    null // ChartRenderingInfo 信息
            );
            fos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /*********************************************************************************************************************
     *
     * 									                             更新所有的数据
     *
     *********************************************************************************************************************/
    public void calculateMovingAverage() {
        stockTransactionDataDao.calculateMovingAverage();
    }

    /**
     * 计算所有股票的LAST_CLOSE_PRICE、CHANGE_AMOUNT、CHANGE_RANGE、CHANGE_RANGE_EX_RIGHT、UP_DOWN字段
     */
    public void writeLastClosePrice() {
        stockTransactionDataDao.writeLastClosePrice();
    }

    /**
     * 调用myquant接口，根据开始时间和结束时间，更新股票的总市值和流通市值
     */
    public void writeMarketValueBetweenDate_myQuant(){
        logger.info("调用myquant接口，根据开始时间和结束时间，更新股票的总市值和流通市值");

        String filePath = PropertiesUtil.getValue(STOCK_RECORD_PROPERTIES, "adam3.api.file.path");
        String writeMarketValueBetweenDate = PropertiesUtil.getValue(STOCK_RECORD_PROPERTIES, "stockRecord.marketValue.writeMarketValueBetweenDate");
        String beginDate = PropertiesUtil.getValue(STOCK_RECORD_PROPERTIES, "stockRecord.marketValue.beginDate");
        String endDate = PropertiesUtil.getValue(STOCK_RECORD_PROPERTIES, "stockRecord.marketValue.endDate");
        beginDate = String.format("%tF", DateUtil.stringToDate(beginDate));
        endDate = String.format("%tF", DateUtil.stringToDate(endDate));

        Process process = null;
        BufferedReader in = null;
        String[] parameterArray = new String[]{"python", filePath, "api",  writeMarketValueBetweenDate, beginDate, endDate};
        try {
            process = Runtime.getRuntime().exec(parameterArray);
            in = new BufferedReader(new InputStreamReader(process.getInputStream(), "gbk"));
            StringBuffer stringBuffer = new StringBuffer();
            String actionStr;
            while ((actionStr = in.readLine()) != null) {
                stringBuffer.append(actionStr);
                logger.debug("接口返回值：" + actionStr);
            }
            if (!PythonApiResult.FINISH.getCode().equals(stringBuffer.toString())){
                logger.warn("调用接口writeMarketValueByCodeAndBetweenDate失败，返回值：" + stringBuffer);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 调用myquant接口，根据开始时间和结束时间，更新股票的pe、pb、ps、peg和dy
     */
    public void writePePbPsPegDyBetweenDate_myQuant(){
        logger.info("调用myquant接口，根据开始时间和结束时间，更新股票的pe、pb、ps、peg和dy");

        String filePath = PropertiesUtil.getValue(STOCK_RECORD_PROPERTIES, "adam3.api.file.path");
        String writePePbPsPegDyBetweenDate = PropertiesUtil.getValue(STOCK_RECORD_PROPERTIES, "stockRecord.pePbPsPegDy.writePePbPsPegDyBetweenDate");
        String beginDate = PropertiesUtil.getValue(STOCK_RECORD_PROPERTIES, "stockRecord.pePbPsPegDy.beginDate");
        String endDate = PropertiesUtil.getValue(STOCK_RECORD_PROPERTIES, "stockRecord.pePbPsPegDy.endDate");
        beginDate = String.format("%tF", DateUtil.stringToDate(beginDate));
        endDate = String.format("%tF", DateUtil.stringToDate(endDate));

        Process process = null;
        BufferedReader in = null;
        String[] parameterArray = new String[]{"python", filePath, "api",  writePePbPsPegDyBetweenDate, beginDate, endDate};
        try {
            process = Runtime.getRuntime().exec(parameterArray);
            in = new BufferedReader(new InputStreamReader(process.getInputStream(), "gbk"));
            StringBuffer stringBuffer = new StringBuffer();
            String actionStr;
            while ((actionStr = in.readLine()) != null) {
                stringBuffer.append(actionStr);
                logger.debug("接口返回值：" + actionStr);
            }
            if (!PythonApiResult.FINISH.getCode().equals(stringBuffer.toString())){
                logger.warn("调用接口writeMarketValueByCodeAndBetweenDate失败，返回值：" + stringBuffer);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * stock_transaction_data表的up_down字段已经在获取数据时就计算好了，所以现在这个方法用不着了。
     */
    public void writeUpDown() {
        stockTransactionDataDao.writeUpDown();
    }

    public void writeMACD() {
        stockTransactionDataDao.writeMACD();
    }

    public void calculateUpDownPercentage() {
        stockTransactionDataDao.calculateUpDownPercentage();
    }

    public void calculateVolatility() {
        stockTransactionDataDao.calculateVolatility();
    }

    public void writeKD() {
        stockTransactionDataDao.writeKD();
    }

    public void writeHa() {
        stockTransactionDataDao.writeHa();
    }

    public void writeBoll() {
        stockTransactionDataDao.writeBoll();
    }

    public void writeBias(){
        stockTransactionDataDao.writeBias();
    }

    public void writeVariance(){
        stockTransactionDataDao.writeVariance();
    }

    public void writeVolumeMa(){
        stockTransactionDataDao.writeVolumeMa();
    }

    public void writeTurnoverMa(){
        stockTransactionDataDao.writeTurnoverMa();
    }

    /*********************************************************************************************************************
     *
     * 									                                              其它
     *
     *********************************************************************************************************************/
    /**
     * 将List类型转换为String类型
     *
     * @param list
     * @return
     */
    @Override
    public String listToString(List list) {
        // TODO Auto-generated method stub
        return null;
    }

    /**
     * 根据开始日期和结束日期，删除表stock_transaction_data中的记录
     */
    public void deleteStockTransactionDataByDate() {
        String beginDate = PropertiesUtil.getValue(STOCK_RECORD_PROPERTIES, "stockRecord.delete.beginDate");
        String endDate = PropertiesUtil.getValue(STOCK_RECORD_PROPERTIES, "stockRecord.delete.endDate");
        stockTransactionDataDao.deleteStockTransactionDataByDate(beginDate, endDate);
    }

    /*********************************************************************************************************************
     *
     * 									                                              实验
     *
     *********************************************************************************************************************/
    public void test() {
        stockTransactionDataDao.test();
    }

}
